繁体   English   中英

用于BeautifulSoup用户的html5lib / lxml示例?

[英]html5lib/lxml examples for BeautifulSoup users?

我正在尝试从BeautifulSoup中退出,我喜欢但它似乎(积极地)不受支持。 我正在尝试使用html5lib和lxml,但似乎无法弄清楚如何使用“ find”和“ findall”运算符。

通过查看html5lib的文档,我想到了一个测试程序:

import cStringIO

f = cStringIO.StringIO()
f.write("""
  <html>
    <body>
      <table>
       <tr>
          <td>one</td>
          <td>1</td>
       </tr>
       <tr>
          <td>two</td>
          <td>2</td
       </tr>
      </table>
    </body>
  </html>
  """)
f.seek(0)

import html5lib
from html5lib import treebuilders
from lxml import etree  # why?

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("lxml"))
etree_document = parser.parse(f)

root = etree_document.getroot()

root.find(".//tr")

但这返回None。 我注意到,如果我执行etree.tostring(root)我会取回所有数据,但是我的所有标签都带有html开头(例如<html:table> )。 但是root.find(".//html:tr")引发root.find(".//html:tr")

有人可以让我回到正确的轨道吗?

您可以使用以下命令关闭名称空间: etree_document = html5lib.parse(t, treebuilder="lxml", namespaceHTMLElements=False)

通常,将lxml.html用于HTML。 然后,您不必担心生成自己的解析器和名称空间。

>>> import lxml.html as l
>>> doc = """
...    <html><body>
...    <table>
...      <tr>
...        <td>one</td>
...        <td>1</td>
...      </tr>
...      <tr>
...        <td>two</td>
...        <td>2</td
...      </tr>
...    </table>
...    </body></html>"""
>>> doc = l.document_fromstring(doc)
>>> doc.finall('.//tr')
[<Element tr at ...>, <Element tr at ...>] #doctest: +ELLIPSIS

仅供参考, lxml.html还允许您使用CSS选择器,我发现这是一种更简单的语法。

>>> doc.cssselect('tr')
[<Element tr at ...>, <Element tr at ...>] #doctest: +ELLIPSIS

看来使用“ lxml” html5lib TreeBuilder会导致html5lib在XHTML命名空间中构建树-这很有意义,因为lxml是XML库,而XHTML是将HTML表示为XML的方式。 您可以将lxml的qname语法与find()方法一起使用,以执行以下操作:

root.find('.//{http://www.w3.org/1999/xhtml}tr')

或者,您可以使用lxml的完整XPath函数来执行以下操作:

root.xpath('.//html:tr', namespaces={'html': 'http://www.w3.org/1999/xhtml'})

lxml文档提供了有关如何使用XML名称空间的更多信息。

我意识到这是一个古老的问题,但我来这里的目的是寻求在其他任何地方都找不到的信息。 我试图用BeautifulSoup抓取一些东西,但是它在某些大块的html上令人窒息。 默认的html解析器显然不如其他可用的宽松。 一个通常首选的解析器是lxml,我相信它会产生与浏览器相同的解析。 BeautifulSoup允许您将lxml指定为源解析器,但是使用它需要一些工作。

首先,您需要html5lib并且还必须安装lxml。 尽管html5lib准备使用lxml(和其他一些库),但两者并未打包在一起。 [对于Windows用户,即使我不喜欢对Win依赖关系大惊小怪,因为我通常通过在与项目相同的目录中进行复制来获得库,但我强烈建议为此使用pip; 很无痛 我认为您需要管理员访问权限。]

然后,您需要编写如下内容:

import urllib2
from bs4 import BeautifulSoup
import html5lib
from html5lib import sanitizer
from html5lib import treebuilders
from lxml import etree

url = 'http://...'

content = urllib2.urlopen(url)
parser = html5lib.HTMLParser(tokenizer=sanitizer.HTMLSanitizer,
                             tree=treebuilders.getTreeBuilder("lxml"),
                             namespaceHTMLElements=False)
htmlData = parser.parse(content)
htmlStr = etree.tostring(htmlData)

soup = BeautifulSoup(htmlStr, "lxml")

然后享用您的美丽汤!

注意解析器上的namespaceHTMLElements = false选项。 这很重要,因为lxml是针对XML而不是HTML的。 因此,它将标记它提供的所有标记属于HTML名称空间。 标签看起来像(例如)

<html:li>

和BeautifulSoup不能很好地工作。

尝试:

root.find('.//{http://www.w3.org/1999/xhtml}tr')

您必须指定名称空间,而不是名称空间前缀( html:tr )。 有关更多信息,请参见lxml文档,尤其是本节:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM