我正在使用BeautifulSoup
来解析一堆可能非常脏的HTML
文档。我偶然发现了一件很奇怪的事。
HTML来自此页面:http://www.wvdnr.gov/
它包含多个错误,如多个<html></html>
、<head>
外的<title>
等。
然而,即使在这些情况下,html5lib通常也能很好地工作。事实上,当我这样做时:
soup = BeautifulSoup(document, "html5lib")
并且我预打印soup
,我看到以下输出:http://pastebin.com/8BKapx88
其中包含大量的CCD_ 7标签。
然而,当我执行soup.find_all("a")
时,我会得到一个空列表。有了lxml
,我也得到了同样的结果。
那么:以前有人偶然发现过这个问题吗?发生了什么事?如何获取html5lib
找到但未随find_all
返回的链接?
即使正确答案是"使用另一个解析器"(感谢@alexe),我也有另一个解决方法。出于某种原因,这也起作用:
soup = BeautifulSoup(document, "html5lib")
soup = BeautifulSoup(soup.prettify(), "html5lib")
print soup.find_all('a')
返回相同的链接列表:
soup = BeautifulSoup(document, "html.parser")
当涉及到解析格式不好且棘手的HTML时,解析器的选择非常重要:
HTML解析器之间也存在差异。如果你给美丽汤一个完美的HTML文档,这些差异并不重要。一个解析器会比另一个更快,但它们都会给你一个看起来与原始HTML文档完全相似的数据结构。
但是,如果文档不是完全形成的,不同的解析器会给出不同的结果。
html.parser
为我工作:
from bs4 import BeautifulSoup
import requests
document = requests.get('http://www.wvdnr.gov/').content
soup = BeautifulSoup(document, "html.parser")
print soup.find_all('a')
演示:
>>> from bs4 import BeautifulSoup
>>> import requests
>>> document = requests.get('http://www.wvdnr.gov/').content
>>>
>>> soup = BeautifulSoup(document, "html5lib")
>>> len(soup.find_all('a'))
0
>>> soup = BeautifulSoup(document, "lxml")
>>> len(soup.find_all('a'))
0
>>> soup = BeautifulSoup(document, "html.parser")
>>> len(soup.find_all('a'))
147
另请参阅:
- 解析器之间的差异