2

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

谢谢。

4

2 回答 2

2

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

使用lxml 的 HTML 解析器,您的问题应该会消失:

import urllib2
from lxml import etree

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

如果您在尝试读取无效 HTML 时发现 lxml 仍然阻塞,则必须找到更宽松的解析器。html5libBeautifulSoup 是 Python 最宽松(也是最慢)的 HTML 解析器:

from bs4 import BeautifulSoup

soup = BeautifulSoup(urllib2.urlopen(url), 'html5lib')
于 2013-05-27T01:31:06.787 回答
1

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

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

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

于 2014-07-27T07:45:39.780 回答