Beautiful Soup - 故障排除

错误处理

BeautifulSoup 中主要有两种错误需要处理。 这两个错误不是来自您的脚本,而是来自代码片段的结构,因为 BeautifulSoup API 会抛出错误。

主要错误如下两个 −

AttributeError

这是由于点符号没有找到当前 HTML 标签的同级标签。 比如你可能遇到过这个错误,因为缺少"anchor tag",cost-key在遍历时会报错,需要 a 标签。

KeyError

如果缺少必需的 HTML 标记属性,则会发生此错误。 例如,如果我们在片段中没有 data-pid 属性,pid 键将抛出键错误。

为避免在解析结果时出现上述两个错误,将绕过该结果以确保不会将格式错误的代码段插入到数据库中 −

except(AttributeError, KeyError) as er:
pass

diagnose()

每当我们发现难以理解 BeautifulSoup 对我们的文档或 HTML 做了什么时,只需将它传递给 diagnostic() 函数即可。 在将文档文件传递给 diagnose() 函数时,我们可以显示不同解析器列表如何处理文档。

下面是一个例子来演示 diagnose() 函数的使用 −

from bs4.diagnose import diagnose

with open("20 Books.html",encoding="utf8") as fp:
   data = fp.read()
   
diagnose(data)

输出

Diagnose

Parsing error

解析错误主要有两种类型。 当您将文档提供给 BeautifulSoup 时,您可能会遇到类似 HTMLParseError 的异常。 您也可能会得到意想不到的结果,其中 BeautifulSoup 解析树看起来与解析文档的预期结果有很大不同。

解析错误都不是BeautifulSoup造成的。 这是因为我们使用外部解析器(html5lib,lxml),因为 BeautifulSoup 不包含任何解析器代码。 解决上述解析错误的一种方法是使用另一个解析器。

from HTMLParser import HTMLParser

try:
   from HTMLParser import HTMLParseError
except ImportError, e:
   # From python 3.5, HTMLParseError is removed. Since it can never be
   # thrown in 3.5, we can just define our own class as a placeholder.
   class HTMLParseError(Exception):
      pass

Python 内置的 HTML 解析器会导致两个最常见的解析错误,HTMLParser.HTMLParserError: malformed start tag 和 HTMLParser.HTMLParserError: bad end tag 解决这个问题,主要是使用另一个解析器:lxml 或 html5lib。

另一种常见的意外行为是您无法在文档中找到已知的标签。 但是,当您运行 find_all() 返回 [] 或 find() 返回 None 时。

这可能是由于 python 内置的 HTML 解析器有时会跳过它不理解的标签。


XML 解析器错误

默认情况下,BeautifulSoup 包将文档解析为 HTML,然而,它非常易于使用,并且使用 beautifulsoup4 以非常优雅的方式处理格式错误的 XML。

要将文档解析为 XML,你需要有 lxml 解析器,你只需要将"xml"作为第二个参数传递给 Beautifulsoup 构造函数 −

soup = BeautifulSoup(markup, "lxml-xml")

soup = BeautifulSoup(markup, "xml")

一个常见的 XML 解析错误是 −

AttributeError: 'NoneType' object has no attribute 'attrib'

如果在使用 find() 或 findall() 函数时某些元素丢失或未定义,则可能会发生这种情况。


其他解析错误

下面给出了我们将在本节中讨论的一些其他解析错误 −

环境问题

除了上述解析错误外,您可能会遇到其他解析问题,例如您的脚本可能在一个操作系统中运行但在另一个操作系统中运行不正常,或者在一个虚拟环境中运行但在另一个虚拟环境中运行不正常或在虚拟环境之外可能无法运行的环境问题。 所有这些问题可能是因为两个环境具有不同的可用解析器库。

建议在您当前的工作环境中了解或检查您的默认解析器。 您可以检查当前工作环境可用的当前默认解析器,或者将所需的解析器库作为第二个参数显式传递给 BeautifulSoup 构造函数。

不区分大小写

由于 HTML 标签和属性不区分大小写,所有三个 HTML 解析器都将标签和属性名称转换为小写。 但是,如果您想保留混合大小写或大写的标记和属性,那么最好将文档解析为 XML。

UnicodeEncodeError

让我们看看下面的代码段 −

soup = BeautifulSoup(response, "html.parser")
   print (soup)

输出

UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'

上述问题可能是由于两种主要情况。 您可能正在尝试打印控制台不知道如何显示的 unicode 字符。 其次,您正在尝试写入文件,并且传入了默认编码不支持的 Unicode 字符。

解决上述问题的一种方法是在制作 soup 之前对响应文本/字符进行编码以获得所需的结果,如下所示 −

responseTxt = response.text.encode('UTF-8')

KeyError: [attr]

这是由于在有问题的标签没有定义 attr 属性时访问标签['attr']引起的。 最常见的错误是:"KeyError:'href'"和"KeyError:'class'"。 如果不确定是否定义了 attr,请使用 tag.get('attr')。

for item in soup.fetch('a'):
   try:
      if (item['href'].startswith('/') or "tutorialspoint" in item['href']):
      (...)
   except KeyError:
      pass # or some other fallback action

AttributeError

你可能会遇到如下的 AttributeError −

AttributeError: 'list' object has no attribute 'find_all'

出现上述错误的主要原因是您希望 find_all() 返回单个标记或字符串。 然而, soup.find_all 返回一个 python 元素列表。

您需要做的就是遍历列表并从这些元素中获取数据。