Skip to main content

故障排除

diagnose()

如果您无法理解Beautiful Soup对文档的作用,请将文档传递到 diagnose() 函数中。 (Beautiful Soup 4.2.0。)Beautiful Soup将打印一个报告,显示不同的解析器如何处理文档,并告诉你,如果你缺少一个解析器,Beautiful Soup可以使用:

from bs4.diagnose import diagnose
with open("bad.html") as fp:
    data = fp.read()
diagnose(data)

# Diagnostic running on Beautiful Soup 4.2.0
# Python version 2.7.3 (default, Aug  1 2012, 05:16:07)
# I noticed that html5lib is not installed. Installing it may help.
# Found lxml version 2.3.2.0
#
# Trying to parse your data with html.parser
# Here's what html.parser did with the document:
# ...

只需看看diagnose()的输出可能会告诉你如何解决这个问题。即使不是,您可以在请求帮助时粘贴 diagnose() 的输出。

解析文档时出错

有两种不同类型的解析错误。有崩溃,你把文档喂给Beautiful Soup,它引发一个异常,通常是 HTMLParser.HTMLParseError。有一个意想不到的行为,美丽的Soup分析树看起来有很多不同于用来创建它的文档。

几乎没有这些问题是Beautiful Soup的问题。这不是因为Beautiful Soup是一个非常好的软件。这是因为Beautiful Soup不包括任何解析代码。相反,它依赖于外部解析器。如果一个解析器不在某个文档上工作,最好的解决方案是尝试一个不同的解析器。有关详细信息和解析器比较,请参阅 安装解析器

最常见的解析错误是 HTMLParser.HTMLParseError: malformed start tagHTMLParser.HTMLParseError: bad end tag。这些都是由Python的内置HTML解析器库生成的,解决方案是 安装lxml或html5lib。

最常见的意外行为类型是找不到您知道的文档在文档中的标记。你看到它进来,但 find_all() 返回 []find() 返回 None。这是Python的内置HTML解析器的另一个常见问题,它有时会跳过它不能理解的标签。再次,解决方案是 安装lxml或html5lib。

版本不匹配问题

  • SyntaxError: Invalid syntax (在行 ROOT_TAG_NAME = u'[document]' 上):由于在Python 3下运行Python 2版本的Beautiful Soup,而不转换代码。

  • ImportError: No module named HTMLParser - 在Python 3下运行Python 2的Beautiful Soup导致的。

  • ImportError: No module named html.parser - 在Python 2下运行Python 3的Beautiful Soup。

  • ImportError: No module named BeautifulSoup - 在没有安装BS3的系统上运行Beautiful Soup 3代码导致的。或者,通过编写Beautiful Soup 4代码,而不知道包名称已更改为 bs4

  • ImportError: No module named bs4 - 在没有安装BS4的系统上运行Beautiful Soup 4代码导致的。

解析XML

默认情况下,Beautiful Soup将文档解析为HTML。要将文档解析为XML,请将“xml”作为第二个参数传递给 BeautifulSoup 构造函数:

soup = BeautifulSoup(markup, "xml")

你需要 有lxml安装

其他解析器问题

  • 如果您的脚本在一台计算机上工作,而不是在另一台计算机上工作,或者在一个虚拟环境中工作,而不是在另一个虚拟环境中工作,例如,您可能已经在安装了lxml的计算机上开发了该脚本,然后尝试在仅安装了html5lib的计算机上运行该脚本。请参阅 解析器之间的区别 为什么这很重要,并通过在 BeautifulSoup 构造函数中提及一个特定的解析器库来解决这个问题。

  • 因为 HTML标记和属性不区分大小写,所有三个HTML解析器将标签和属性名称转换为小写。也就是说,标记<TAG> </ TAG>被转换为<tag> </ tag>。如果要保留混合大小写或大写标签和属性,您需要使用 将文档解析为XML。

  • UnicodeEncodeError: 'charmap' codec can't encode character u'\xfoo' in position bar (或任何其他 UnicodeEncodeError) - 这不是Beautiful Soup的问题。这个问题出现在两种主要情况下。首先,当您尝试打印控制台不知道如何显示的Unicode字符时。 (请参阅 这个页面在Python wiki上 获取帮助。)其次,当您写入文件并传递默认编码不支持的Unicode字符时。在这种情况下,最简单的解决方案是使用 u.encode("utf8") 将Unicode字符串显式编码为UTF-8。

  • KeyError: [attr] - 当有问题的标记未定义 attr 属性时,通过访问 tag['attr'] 引起。最常见的错误是 KeyError: 'href'KeyError: 'class'。如果不确定 attr 是否定义,请使用 tag.get('attr'),就像使用Python字典一样。

  • AttributeError: 'ResultSet' object has no attribute 'foo' - 这通常发生,因为您期望 find_all() 返回单个标签或字符串。但是 find_all() 返回一个_list_的标签和字符串 - 一个 ResultSet 对象。你需要遍历列表,看看每一个的 .foo。或者,如果你真的只想要一个结果,你需要使用 find() 而不是 find_all()

  • AttributeError: 'NoneType' object has no attribute 'foo' - 这通常发生,因为你调用 find(),然后尝试访问结果的 .foo` 属性。但在你的情况下,find() 没有找到任何东西,所以它返回 None,而不是返回一个标签或字符串。你需要弄清楚为什么你的 find() 调用不返回任何东西。

提高性能

Beautiful Soup永远不会像解析器一样快,它坐在上面。如果响应时间很关键,如果你按小时支付计算机时间,或者有任何其他原因,计算机时间比程序员时间更有价值,你应该忘记Beautiful Soup,直接在 lxml 顶上工作。

也就是说,有些事情你可以做的加快Beautiful Soup。如果你不使用lxml作为底层解析器,我的建议是 开始。Beautiful Soup使用lxml解析文档比使用html.parser或html5lib显着更快。

您可以通过安装 cchardet 库来显着加快编码检测速度。

仅解析文档的一部分 不会节省你很多时间解析文档,但它可以节省大量的内存,它会使 searching 的文档更快。