BeautifulSoup - lxml 和 html5lib 解析器抓取差异

Posted

技术标签:

【中文标题】BeautifulSoup - lxml 和 html5lib 解析器抓取差异【英文标题】:BeautifulSoup - lxml and html5lib parsers scraping differences 【发布时间】:2014-05-06 23:28:29 【问题描述】:

我正在使用 BeautifulSoup 4Python 2.7。我想从网站中提取某些元素(数量,请参见下面的示例)。出于某种原因,lxml 解析器不允许我从页面中提取所有需要的元素。它只会打印前三个元素。我正在尝试使用 html5lib 解析器来查看是否可以提取所有这些。

该页面包含多个项目,以及它们的价格和数量。包含每个项目所需信息的代码部分如下所示:

<td class="size-price last first" colspan="4">
                    <span>453 grams </span>
            <span> <span class="strike">$619.06</span> <span class="price">$523.91</span>
                    </span>
                </td>

让我们考虑以下三种情况:

案例 1 - 数据:

#! /usr/bin/python
from bs4 import BeautifulSoup
data = """
<td class="size-price last first" colspan="4">
                    <span>453 grams </span>
            <span> <span class="strike">$619.06</span> <span class="price">$523.91</span>
                    </span>
                </td>"""                
soup = BeautifulSoup(data)
print soup.td.span.text

打印:

453 grams 

案例 2 - LXML:

#! /usr/bin/python
from bs4 import BeautifulSoup
from urllib import urlopen
webpage = urlopen('The URL goes here')
soup=BeautifulSoup(webpage, "lxml")
print soup.find('td', 'class': 'size-price').span.text

打印:

453 grams

案例 3 - HTML5LIB:

#! /usr/bin/python
from bs4 import BeautifulSoup
from urllib import urlopen
webpage = urlopen('The URL goes here')
soup=BeautifulSoup(webpage, "html5lib")
print soup.find('td', 'class': 'size-price').span.text

我收到以下错误:

Traceback (most recent call last):
  File "C:\Users\Dom\Python-Code\src\Testing-Code.py", line 6, in <module>
    print soup.find('td', 'class': 'size-price').span.text
AttributeError: 'NoneType' object has no attribute 'span'

我必须如何调整我的代码才能使用 html5lib 解析器提取我想要的信息?如果我在使用 html5lib 后简单地在控制台中打印汤,我可以看到所有需要的信息,所以我认为它可以让我得到我想要的。 lxml 解析器并非如此,所以我也很好奇,如果我使用 lxml 解析器,lxml 解析器似乎没有提取所有数量:

print [td.span.text for td in soup.find_all('td', 'class': 'size-price')]

【问题讨论】:

html5lib 省略了td 标记并将所有内容都放在了html 正文中——这是因为td 周围没有table 标记,而html5lib 对此很关心。 有趣,所以现在我应该如何使用 html5lib 提取我想要的元素 好吧,你为什么要使用html5lib?仅供参考,您也可以使用html.parser,例如:BeautifulSoup(webpage, 'html.parser') RuntimeWarning: Python 的内置 HTMLParser 无法解析给定的文档。这不是 Beautiful Soup 中的错误。最好的解决方案是安装一个外部解析器(lxml 或 html5lib),并将 Beautiful Soup 与该解析器一起使用。请参阅crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser 寻求帮助。 "Python's built-in HTMLParser cannot parse the given document. This is not a bug in Beautiful Soup. The best solution is to install an external parser (lxml or html5lib), and use Beautiful Soup with that parser. Gotcha :) 我可以看到您尝试解析的整个 html 文档(或链接)吗? 【参考方案1】:
from lxml import etree

html = 'your html'
tree = etree.HTML(html)
tds = tree.xpath('.//td[@class="size-price last first"]')
for td in tds:
    price = td.xpath('.//span[@class="price"]')[0].text
    strike = td.xpath('.//span[@class="strike"]')[0].text
    spans = td.xpath('.//span')
    quantity = [i.text for i in spans if 'grams' in i.text][0].strip(' ')

【讨论】:

【参考方案2】:

试试下面的:

    from bs4 import BeautifulSoup
    data = """
    <td class="size-price last first" colspan="4">
                <span>453 grams </span>
        <span> <span class="strike">$619.06</span> <span 
    class="price">$523.91</span>
                </span>
            </td>"""                
    soup = BeautifulSoup(data)
    text = soup.get_text(strip=True)
    print text

【讨论】:

以上是关于BeautifulSoup - lxml 和 html5lib 解析器抓取差异的主要内容,如果未能解决你的问题,请参考以下文章

python模块--BeautifulSoup4 和 lxml

BeautifulSoup 和 lxml.html - 更喜欢啥? [复制]

Jupyter 笔记本中的 BeautifulSoup 和 lxml

python中的beautifulsoup和xpath有啥异同点

lxml / BeautifulSoup 解析器警告

BeautifulSoup - lxml 和 html5lib 解析器抓取差异