python - beautifulSoup 不正确嵌套 <ul> 的屏幕抓取列表

标签 python screen-scraping beautifulsoup web-scraping

我是 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)。这些在教会中没有明显的身份或治理(即它不是建筑物)——相反,它是分配给牧师照顾的非领土群体。

解析

我认为你应该采取渐进的方法:

  1. 找到所有的li元素,每一个都是一个“item”
  2. 项目的名称是第一个文本节点
  3. 找到所有 i 元素:这些是键、属性值、列行等
  4. 直到下一个 i 的所有文本(由 br 分隔)都是该键的值。

此页面的一个特殊问题是它的 html 病态地糟糕以至于您需要使用 MinimalSoup 才能正确解析它。特别是,BeautifulSoup 认为 li 元素是嵌套的,因为文档中的任何地方都没有 olul!

此代码将为您提供元组列表的列表。每个元组都是一个项目的 ('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/

相关文章:

Python Scrapy,如何为项目定义管道?

python - 无法在 Instagram 公共(public)帐户上抓取超过 12 个帖子

python - Beautifulsoup,找到htm中唯一没有属性的标签

python - Beautifulsoup 构造函数及其参数

python - 如何读取和解码印度 Aadhaar 卡图像上的安全二维码

python - 无法使用 Pafy/youtube_dl 初始化新 URL,我收到 "ERROR: This video is unavailable"

python - 自定义 distutils 命令

python - 使用 Python 加载 DLL 时出现错误 193

java - 如何使用 HTML Parser 获取 HTML 页面中所有标签的完整信息

python - 在 Python 中屏幕抓取基于 Javascript 的网页