【问题标题】:Beautiful Soup raises UnicodeEncodeError "ordinal not in range(128)"Beautiful Soup 引发 UnicodeEncodeError “序数不在范围内(128)”
【发布时间】:2012-01-27 14:59:07
【问题描述】:

我正在尝试解析从网上下载的任意文档,是的,我无法控制它们的内容。

自从Beautiful Soup won't choke if you give it bad markup... 我想知道为什么有时文档的部分格式不正确时它会给我带来这些麻烦,以及是否有办法让它恢复到下一个可读部分文档,不管这个错误。

发生错误的行是第 3 行:

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)

【问题讨论】:

  • 您向 BeautifulSoup 提供什么样的输入?根据报错信息,可能你正在解析一些非ascii数据(例如包含非拉丁字符)?
  • 我正在解析的数据来自野网,其中一部分肯定是非ascii的。

标签: python unicode beautifulsoup


【解决方案1】:

是的,如果您有非 ASCII 名称的元素 (&lt;café&gt;),它会窒息。对于 XML,这甚至不是“糟糕的标记”……

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

您可以通过将第 259 和 371 行从 except AttributeError: 更改为 except AttributeError, UnicodeError: 来破解 sgmllib 的修复程序,但这并不是一个很好的修复程序。覆盖该方法的其余部分也不是一件容易的事。

您要解析的是什么? BeautifulStoneSoup 的用处总是值得怀疑——XML 没有 HTML 所具备的大量可怕的解析器黑客,所以通常损坏的 XML 不是 XML。因此,您通常应该使用普通的旧 XML 解析器(例如,使用标准 DOM 或 etree)。对于解析一般 HTML,html5lib 是这些天您更好的选择。

【讨论】:

  • 您建议的修复根本不起作用,因为当解析器尝试使用仅支持非-ascii 字符。这意味着即使在UnicodeEncodeError 出现之前,有效的开始标签也会被跳过。
  • @bobince,我听从了你的建议,并为 *_endtag 和 *_startag 方法添加了 UnicodeErrorUnicodeEncodeErrorUnicodeDecodeError(参见 gist.github.com/1520499#L331)——现在我得到了结果已经预料到,它只是跳过二进制部分并仅提取相关块。谢谢!
【解决方案2】:

如果在 Python 3.0 之前的 Python 版本中输入中有非 ascii 字符,则会发生这种情况

如果您尝试在包含字符值 > 128(ANSII 和 unicode)的字符的字符串上使用 str(...),则会引发此异常。

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

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

【讨论】:

    猜你喜欢
    • 2023-01-24
    • 2018-02-07
    • 1970-01-01
    • 2011-11-19
    • 2017-05-10
    • 2019-11-10
    • 2021-05-14
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多