我是 BeautifulSoup 的(非常)新手,在过去的三天里,我试图从 http://www.ucanews.com/diocesan-directory/html/ordinary-of-philippine-cagayandeoro-parishes.html 中获取教堂列表。 .
数据似乎没有正确嵌套,只是为了展示目的而标记。据推测,层次结构是
Parishes
District
(data)
Vicariate
(data)
Church
(data)
然而我所看到的是每个教堂都以一个项目符号开头,每个条目都由两个换行符分隔。我之后的字段名称是斜体的,并用“:”与实际数据分开。每个单元条目(学区 |Vicariate|Parish)可能有一个或多个数据字段。
到目前为止,我可以梳理出一些数据,但无法显示实体的名称。
soup=BeautifulSoup(page)
for e in soup.table.tr.findAll('i'):
print e.string, e.nextSibling
最后,我希望按列转换数据:district, vicariate, parish, address, phone, titular, parish priest, <field8>, <field9>, <field99>
希望在正确的方向上得到很好的插入。
最佳答案
不幸的是,这会有点复杂,因为这种格式有一些您需要的数据没有被清晰的标记包含。
数据模型
另外,您对嵌套的理解也不完全正确。实际的天主教堂结构(不是这个文档结构)更像是:
District (also called deanery or vicariate. In this case they all seem to be Vicariates Forane.)
Cathedral, Parish, Oratory
请注意,没有要求一个教区属于一个地区/教区,尽管他们通常这样做。我认为该文件是说在地区之后列出的所有内容都属于该地区,但您无法确定。
里面还有一个入口不是教堂而是社区(San Lorenzo Filipino-Chinese Community)。这些在教会中没有明显的身份或治理(即它不是建筑物)——相反,它是分配给牧师照顾的非领土群体。
解析
我认为你应该采取渐进的方法:
- 找到所有的
li
元素,每一个都是一个“item” - 项目的名称是第一个文本节点
- 找到所有
i
元素:这些是键、属性值、列行等 - 直到下一个
i
的所有文本(由br
分隔)都是该键的值。
此页面的一个特殊问题是它的 html 病态地糟糕以至于您需要使用 MinimalSoup
才能正确解析它。特别是,BeautifulSoup
认为 li
元素是嵌套的,因为文档中的任何地方都没有 ol
或 ul
!
此代码将为您提供元组列表的列表。每个元组都是一个项目的 ('key','value')
对。
一旦你有了这个数据结构,你就可以按照你喜欢的方式规范化、转换、嵌套等,而把 HTML 留在后面。
from BeautifulSoup import MinimalSoup
import urllib
fp = urllib.urlopen("http://www.ucanews.com/diocesan-directory/html/ordinary-of-philippine-cagayandeoro-parishes.html")
html = fp.read()
fp.close()
soup = MinimalSoup(html);
root = soup.table.tr.td
items = []
currentdistrict = None
# this loops through each "item"
for li in root.findAll(lambda tag: tag.name=='li' and len(tag.attrs)==0):
attributes = []
parishordistrict = li.next.strip()
# look for string "district" to determine if district; otherwise it's something else under the district
if parishordistrict.endswith(' District'):
currentdistrict = parishordistrict
attributes.append(('_isDistrict',True))
else:
attributes.append(('_isDistrict',False))
attributes.append(('_name',parishordistrict))
attributes.append(('_district',currentdistrict))
# now loop through all attributes of this thing
attributekeys = li.findAll('i')
for i in attributekeys:
key = i.string # normalize as needed. Will be 'Address:', 'Parochial Victor:', etc
# now continue among the siblings until we reach an <i> again.
# these are "values" of this key
# if you want a nested key:[values] structure, you can use a dict,
# but beware of multiple <i> with the same name in your logic
next = i.nextSibling
while next is not None and getattr(next, 'name', None) != 'i':
if not hasattr(next, 'name') and getattr(next, 'string', None):
value = next.string.strip()
if value:
attributes.append((key, value))
next = next.nextSibling
items.append(attributes)
from pprint import pprint
pprint(items)
关于python - beautifulSoup 不正确嵌套 <ul> 的屏幕抓取列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8367499/