Beautiful Soup - 故障排除


错误处理

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

两个主要错误如下 -

属性错误

这是由于点符号找不到当前 HTML 标记的同级标记而导致的。例如,您可能遇到过这个错误,因为缺少“锚标记”,cost-key在遍历时会抛出错误并需要锚标记。

按键错误

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

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

except(AttributeError, KeyError) as er:
pass

诊断()

每当我们发现难以理解 BeautifulSoup 对文档或 HTML 的作用时,只需将其传递给diagnose() 函数即可。将文档文件传递给diagnose()函数时,我们可以展示不同解析器的列表如何处理文档。

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

from bs4.diagnose import diagnose

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

输出

诊断

解析错误

解析错误主要有两种类型。当您将文档提供给 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。

另一种常见的意外Behave是您在文档中找不到已知的标签。但是,当您运行 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。

Unicode编码错误

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

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

输出

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

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

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

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

密钥错误:[attr]

这是由于当相关标签未定义 attr 属性时访问 tag['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: 'list' object has no attribute 'find_all'

发生上述错误主要是因为您期望 find_all() 返回单个标记或字符串。然而, soup.find_all 返回一个 python 元素列表。

您需要做的就是迭代列表并从这些元素中捕获数据。