簡體   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