BeautifulSoup报”AttributeError: ‘NavigableString’ object has no attribute ‘find_all’ “异常的原因以及解决办法

  • Post category:Python

首先,让我们先解释一下BeautifulSoupBeautifulSoup是一个Python库,用于从HTML和XML文件中提取数据。它使用了类似DOM或XML的解析方式,使得我们能够获取数据更加方便快捷。

现在,让我们来看看AttributeError: 'NavigableString' object has no attribute 'find_all'报错的原因和解决办法。

当我们使用find_all()在一个字符串类型的对象上调用时,它会报错,因为这是一个不可迭代的对象。在BeautifulSoup中,字符串类型的对象表示的是HTML或XML中的文本节点,而不是标签节点。

下面是一个例子:

from bs4 import BeautifulSoup

html_doc = """
<html>
    <head>
        <title>这是一个例子</title>
    </head>
    <body>
        <p>这是一个段落。</p>
    </body>
</html>
"""

soup = BeautifulSoup(html_doc, 'html.parser')
title = soup.title.string
paragraph = soup.p.string
print(type(title))      # <class 'bs4.element.NavigableString'>
print(type(paragraph))  # <class 'bs4.element.NavigableString'>

# 下面这行代码会报错
links = paragraph.find_all('a')

在上述代码中,我们首先将html_doc传递给BeautifulSoup,然后,我们获取了标题和段落节点的string,并查看它们的类型,确认它们是NavigableString类型的对象。接着,我们试图使用paragraph.find_all('a')从段落中获取所有链接,但是,这个操作会导致AttributeError: 'NavigableString' object has no attribute 'find_all' 的错误。

因此,我们应该确保在使用find_all()等方法之前,首先要确定我们在操作的对象是标签节点,而不是文本节点。我们可以使用find()或选择器语法(如.select().select_one())来获取标签节点。如果我们要获取标签节点的文本内容,我们可以使用标签节点的string属性或get_text()方法。

下面是一个更新后的例子:

from bs4 import BeautifulSoup

html_doc = """
<html>
    <head>
        <title>这是一个例子</title>
    </head>
    <body>
        <p>这是一个<a href="#">链接</a>。</p>
    </body>
</html>
"""

soup = BeautifulSoup(html_doc, 'html.parser')
title = soup.title.string
paragraph = soup.p
print(type(title))      # <class 'bs4.element.NavigableString'>
print(type(paragraph))  # <class 'bs4.element.Tag'>

links = paragraph.find_all('a')
print(links)            # [<a href="#">链接</a>]

在这里,我们使用soup.p获取了段落标签节点,而不是使用soup.p.string获取段落文本。这样做后,我们就可以使用find_all()方法成功查找链接节点。

总结:

  • 该错误的原因是在不能使用find_all()等方法之前,首先要确认我们在操作的对象是否是标签节点,而不是文本节点。
  • 解决方法是使用find()或选择器语法(如.select().select_one())来获取标签节点。如果要获取标签节点的文本内容,则可以使用标签节点的string属性或get_text()方法。