【问题标题】:Why does lxml spit out an error at times (but not usual) in Python?为什么 lxml 在 Python 中有时(但不常见)会吐出错误?
【发布时间】:2025-12-26 00:15:07
【问题描述】:

我经常在 Python 中使用lxml 模块从一些网站上抓取数据,而且我通常对这个模块感到满意。但是,当我尝试抓取时,有时我会在etree.fromstring() 调用时遇到lxml.etree.XMLSyntaxError: AttValue: " or ' expected 错误,但通常不会。我无法澄清我看到该错误的频率,但我认为千分之一甚至数万次,我都会遇到该错误。当我在错误发生并且脚本停止后立即运行完全相同的脚本时,我看不到错误并且脚本按预期运行良好。为什么它偶尔会吐出一个错误?有没有办法处理这个问题?我在实例化 urllib2.urlopen() 函数时遇到了类似的问题,但是由于我最近没有看到来自urllib2 的错误,所以我现在无法写出来自它的确切错误消息。

谢谢。

【问题讨论】:

  • 也许是 invalid XML?捕获导致错误的数据并使用XML/XHTML validator 对其进行验证。 (对于相同的数据,错误不太可能不确定地发生 - 也许服务器返回了其他内容?)

标签: python web-scraping urllib2 lxml elementtree


【解决方案1】:

网站是用(通常是无效的)HTML 而非 XML 编写的。您不应该将 HTML 视为 XML。

使用lxml's HTML parser,您的问题应该会消失:

import urllib2
from lxml import etree

parser = etree.HTMLParser()
tree = etree.parse(urllib2.urlopen(url), parser)

如果您在尝试读取无效 HTML 时发现 lxml 仍然阻塞,您将不得不找到更宽松的解析器。 html5lib with BeautifulSoup 是 Python 最宽松(也是最慢)的 HTML 解析器:

from bs4 import BeautifulSoup

soup = BeautifulSoup(urllib2.urlopen(url), 'html5lib')

【讨论】:

  • 也许,我应该澄清更多,但我通常看不到错误;我只是遇到错误,比如说,当我尝试抓取完全相同的页面时,有 1,000~10,000 次错误,每当我尝试抓取时,它都是完全相同的 XML。此外,该页面由严格的 XML 文件组成,而不是您在网络上经常看到的无效 HTML 文件。最后,即使我看到错误,下次我尝试抓取包含完全相同的 XML 文件的同一页面(文件中的任何内容都没有更改)时,错误也不会再发生......
【解决方案2】:

我还有一个问题,lxml 的iterparse() 偶尔会以非常不可预测的模式抛出AttValue: ' expected。我知道我发送的 XML 是有效的,并且重新运行相同的脚本通常会使其工作(或在完全不同的点上失败)。

最后,我设法创建了一个可以重新运行的测试用例,它会立即完成或在看似随机的结果中引发AttValue 错误。这是我做错的:

我对@9​​87654324@ 的输入是我自己编写的一个类似文件的对象(我正在处理来自请求的 HTTP 响应流,但必须先解压缩它)。在编写read() 方法时,我作弊并忽略了size 参数。相反,我只需解压缩一大块固定大小的压缩字节,然后返回解压缩后的任何字节序列——通常比 32k 的 lxml 请求多得多!
我怀疑这会导致 lxml 内部某处的缓冲区溢出,从而导致上述问题。一旦我停止返回比 lxml 请求更多的字节,这些随机错误就会消失。

【讨论】:

    最近更新 更多