Beautiful Soup 报告 UnicodeEncodeError "ordinal not in range(128)
我正在尝试解析从网上下载的各种文档,没错,我对这些文档的内容没有控制权。
因为Beautiful Soup在处理糟糕的标记时不会出错...,我想知道为什么当文档的某一部分格式不正确时,它会出现问题,是否有办法让它继续解析文档中下一个可以读取的部分,而不受这个错误的影响。
错误发生的那一行是第三行:
from BeautifulSoup import BeautifulSoup as doc_parser
reader = open(options.input_file, "rb")
doc = doc_parser(reader)
命令行的完整输出是:
Traceback (most recent call last):
File "./grablinks", line 101, in <module>
sys.exit(main())
File "./grablinks", line 88, in main
links = grab_links(options)
File "./grablinks", line 36, in grab_links
doc = doc_parser(reader)
File "/usr/local/lib/python2.7/dist-packages/BeautifulSoup.py", line 1519, in __init__
BeautifulStoneSoup.__init__(self, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/BeautifulSoup.py", line 1144, in __init__
self._feed(isHTML=isHTML)
File "/usr/local/lib/python2.7/dist-packages/BeautifulSoup.py", line 1186, in _feed
SGMLParser.feed(self, markup)
File "/usr/lib/python2.7/sgmllib.py", line 104, in feed
self.goahead(0)
File "/usr/lib/python2.7/sgmllib.py", line 143, in goahead
k = self.parse_endtag(i)
File "/usr/lib/python2.7/sgmllib.py", line 320, in parse_endtag
self.finish_endtag(tag)
File "/usr/lib/python2.7/sgmllib.py", line 358, in finish_endtag
method = getattr(self, 'end_' + tag)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 15-16: ordinal not in range(128)
2 个回答
如果你在使用 Python 3.0 之前的版本时,输入中包含非 ASCII 字符,就会出现这个问题。
当你尝试对一个包含字符值大于 128 的字符串使用 str(...)
时,就会引发这个异常(错误)。这些字符包括 ANSI 和 Unicode 字符。
这个错误可能是因为 getattr
尝试在一个 Unicode 字符串上使用 str
,它“认为”这样做是安全的,因为在 Python 3.0 之前,标识符(变量名等)不能包含 Unicode 字符。
检查一下你的 HTML 中是否有 Unicode 字符。尝试替换或编码这些字符,如果还是不行,请告诉我们。
嗯,如果你有一些名字里包含非ASCII字符的元素(比如<café>
),那就会出问题。这其实并不是‘糟糕的标记’,在XML中也是如此……
这是sgmllib
中的一个bug,而BeautifulSoup正是用这个库的。它试图找到和标签同名的自定义方法,但在Python 2中,方法名是字节字符串,所以即使是去找一个包含非ASCII字符的方法,也永远找不到,这就出错了。
你可以通过修改sgmllib
中的第259和371行,把except AttributeError:
改成except AttributeError, UnicodeError:
来临时解决这个问题,但这并不是一个好的解决方案。想要覆盖这个方法的其他部分也不简单。
你想解析的是什么呢?BeautifulStoneSoup的实用性一直都值得怀疑——XML没有HTML那样复杂的解析问题,所以一般来说,损坏的XML就不算XML。因此,你通常应该使用一个普通的XML解析器(比如标准的DOM或etree)。如果是解析一般的HTML,现如今html5lib
是更好的选择。