2011-12-25 96 views
5

我想解析任意文件从野外web下载,是的,我没有控制他们的内容。美丽的汤引发UnicodeEncodeError“序号不在范围内(128)”

由于Beautiful Soup won't choke if you give it bad markup...我不知道为什么它给我的那些乡下人起坐时有时,DOC的部分的格式不正确,以及是否有一种方法,使其恢复到文档中的下一个可读部分,不管这错误。

发生错误的是第三一个行:

from BeautifulSoup import BeautifulSoup as doc_parser 
reader = open(options.input_file, "rb") 
doc = doc_parser(reader) 

CLI完整的输出是:

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) 
+0

你给BeautifulSoup喂什么样的输入?根据错误信息,也许你正在解析一些非ascii数据(例如包含非拉丁字符)? – 2011-12-25 13:50:36

+0

我解析的数据来自野外的网站,它的一部分绝对不是ascii。 – 2011-12-26 04:13:34

回答

2

是的,如果你有非ASCII名称的元素(<café>),它会窒息。对于XML,这甚至不是'糟糕的标记'...

这是BeautifulSoup使用的sgmllib中的一个错误:它试图找到与标记名称相同的自定义方法,但在Python 2中方法名称是字节字符串所以即使看起来的非ASCII字符的方法永远不会出现失败。

您可以通过将行259和371从except AttributeError:更改为except AttributeError, UnicodeError:来修复sgmllib,但这不是一个很好的解决方法。重写该方法的其余部分也不是微不足道的。

你试图解析什么? BeautifulStoneSoup的确总是有用的 - XML并没有HTML所具有的可怕的解析器黑客,所以一般来说,破碎的XML不是XML。因此,您通常应该使用普通的旧XML解析器(例如,使用标准的DOM或etree)。对于解析一般的HTML,这几天你最好选择html5lib

+0

您建议的修复程序根本不会真正起作用,因为错误实际上较早开始,当解析器尝试使用仅支持非ascii字符的正则表达式匹配_start_标记时。这意味着即使在发生UnicodeEncodeError之前,也会跳过有效的开始标记。 – ekhumoro 2011-12-25 18:14:26

+0

@bobince,我按照你的建议,为* _endtag和* _startag方法添加了'UnicodeError','UnicodeEncodeError'和'UnicodeDecodeError'(见https://gist.github.com/1520499#L331) - 现在我已经我期望的结果,它只是跳过二进制部分,只提取相关的块。谢谢! – 2011-12-26 04:12:08

0

出现这种情况,如果有在以往的Python版本输入非ASCII字符Python 3.0

如果您试图对包含char值> 128(ANSII & unicode)的字符的字符串使用str(...),则此例外是r aised。

在这里,错误可能发生的原因是getattr试图在unicode字符串上使用str - 它“认为”它可以安全地执行此操作,因为在3.0之前的python版本中,标识符不能包含unicode。

检查您的HTML是否有unicode字符。尝试替换/编码这些,如果它仍然不起作用,告诉我们。