![](/img/trans.png)
[英]BeautifulSoup - lxml and html5lib parsers scraping differences
[英]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.