实际有效的 Python html 解析
Posted
技术标签:
【中文标题】实际有效的 Python html 解析【英文标题】:Python html parsing that actually works 【发布时间】:2011-05-06 02:38:10 【问题描述】:我正在尝试在 Python 中解析一些 html。以前有一些方法确实有效……但现在,如果没有变通办法,我什么都不能真正使用。
SGMLParser 消失后beautifulsoup 出现问题 html5lib 无法解析“外面”的一半内容 lxml 试图对典型的 html “太正确”(属性和标签不能包含未知的命名空间,否则会抛出异常,这意味着几乎没有 Facebook 连接的页面可以被解析)现在还有哪些其他选择? (如果他们支持 xpath,那就太好了)
【问题讨论】:
您需要向我们提供当前方法失败的页面示例。否则,我们如何知道我们提出的解决方案是否能解决您的问题?另外,不要忘记在code.google.com/p/html5lib/issues/entry 报告 html5lib 错误 【参考方案1】:确保在使用 lxml
解析 HTML 时使用 html
模块:
>>> from lxml import html
>>> doc = """<html>
... <head>
... <title> Meh
... </head>
... <body>
... Look at this interesting use of <p>
... rather than using <br /> tags as line breaks <p>
... </body>"""
>>> html.document_fromstring(doc)
<Element html at ...>
所有错误和异常都会消失,您将得到一个速度惊人的解析器,它通常比 BeautifulSoup 更好地处理 HTML 汤。
【讨论】:
这很有趣。我总是通过 treebuilder 使用 lxml。我很确定 HTMLParser 使用这种方式强制 html 模式。显然不是。 lxml.html 正确解析<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en" xmlns:fb="http://www.facebook.com/2008/fbml">
之类的内容。 (其中 lxml 抛出异常)
很高兴听到 thinks 对您很有效!感谢您接受答案。【参考方案2】:
我已经将 pyparsing 用于许多 HTML 页面抓取项目。它是 BeautifulSoup 和完整的 HTML 解析器之间的一种中间立场,以及正则表达式的太低级方法(这种方式很疯狂)。
使用 pyparsing,您通常可以通过识别您尝试提取的页面或数据的特定子集来获得良好的 HTML 抓取结果。这种方法避免了尝试解析页面上的所有内容的问题,因为您感兴趣的区域之外的一些有问题的 HTML 可能会导致全面的 HTML 解析器失效。
虽然这听起来像是一种美化的正则表达式方法,但 pyparsing 提供了用于处理 HTML 或 XML 标记文本的内置函数。 Pyparsing 避免了许多阻碍基于正则表达式的解决方案的陷阱:
接受空白而不在你的表情中乱扔“\s*” 处理标签中的意外属性 以任意顺序处理属性 处理标签中的大写/小写 使用命名空间处理属性名称 处理双引号、单引号或无引号中的属性值 处理空标签(<blah />
形式的标签)
返回已解析的标签数据,具有对标签属性的对象属性访问权限
这是一个来自 pyparsing wiki 的简单示例,它从网页中获取 <a href=xxx>
标记:
from pyparsing import makeHTMLTags, SkipTo
# read HTML from a web page
page = urllib.urlopen( "http://www.yahoo.com" )
htmlText = page.read()
page.close()
# define pyparsing expression to search for within HTML
anchorStart,anchorEnd = makeHTMLTags("a")
anchor = anchorStart + SkipTo(anchorEnd).setResultsName("body") + anchorEnd
for tokens,start,end in anchor.scanString(htmlText):
print tokens.body,'->',tokens.href
这将拉出<a>
标签,即使页面的其他部分包含有问题的 HTML。 pyparsing wiki 上还有其他 HTML 示例:
Pyparsing 并不是这个问题的万无一失的解决方案,但是通过向您公开解析过程,您可以更好地控制您特别感兴趣的 HTML 片段,处理它们,然后跳过其余部分。
【讨论】:
Pyparsing 不再托管在 wikispaces.com 上。转至github.com/pyparsing/pyparsing【参考方案3】:html5lib 无法解析“外面”的一半
这听起来非常难以置信。 html5lib 使用的算法与最近版本的 Firefox、Safari 和 Chrome 中实现的算法完全相同。如果该算法破坏了一半的网络,我想我们会听到的。如果您对此有特殊问题,请提交错误。
【讨论】:
好吧 - 也许不是一半,但它在一些脚本标签上坏了(不记得该网站),错过了一大块 youtube(有时)和我尝试使用它的其他网站。我会报告我可以复制的东西。 脚本标签确实是一团糟,但它们的处理方式最近发生了很大变化。我希望你会发现它现在工作得更好了。【参考方案4】:如果您正在抓取内容,避开烦人的细节的绝佳方法是 sitescraper 包。它使用机器学习来确定要为您检索哪些内容。
来自主页:
>>> from sitescraper import sitescraper
>>> ss = sitescraper()
>>> url = 'http://www.amazon.com/s/ref=nb_ss_gw?url=search-alias%3Daps&field-keywords=python&x=0&y=0'
>>> data = ["Amazon.com: python",
["Learning Python, 3rd Edition",
"Programming in Python 3: A Complete Introduction to the Python Language (Developer's Library)",
"Python in a Nutshell, Second Edition (In a Nutshell (O'Reilly))"]]
>>> ss.add(url, data)
>>> # we can add multiple example cases, but this is a simple example so 1 will do (I generally use 3)
>>> # ss.add(url2, data2)
>>> ss.scrape('http://www.amazon.com/s/ref=nb_ss_gw?url=search-alias%3Daps&field- keywords=linux&x=0&y=0')
["Amazon.com: linux", ["A Practical Guide to Linux(R) Commands, Editors, and Shell Programming",
"Linux Pocket Guide",
"Linux in a Nutshell (In a Nutshell (O'Reilly))",
'Practical Guide to Ubuntu Linux (Versions 8.10 and 8.04), A (2nd Edition)',
'Linux Bible, 2008 Edition: Boot up to Ubuntu, Fedora, KNOPPIX, Debian, openSUSE, and 11 Other Distributions']]
【讨论】:
【参考方案5】:我认为问题在于大多数 HTML 格式不正确。 XHTML 试图解决这个问题,但它从未真正流行起来——尤其是当大多数浏览器对格式错误的代码进行“智能变通”时。
甚至在几年前,我尝试为一个原始蜘蛛类型的应用程序解析 HTML,但发现问题太难了。我怀疑自己可能会写,虽然我们不能是唯一遇到这个问题的人!
【讨论】:
以上是关于实际有效的 Python html 解析的主要内容,如果未能解决你的问题,请参考以下文章