CodeGym /课程 /Python SELF ZH /用 find 和 find_all 方法进行目标爬取的元素查找

用 find 和 find_all 方法进行目标爬取的元素查找

Python SELF ZH
第 32 级 , 课程 1
可用

1. 为什么要使用 findfind_all

今天咱们聊聊两个主要的方法,它们可以帮助我们高效地、有针对性地从 HTML 文档中提取元素:findfind_all

在 dive 进代码之前,先讨论一下为什么需要这些方法。想像一下网页就像是一个巨大的图书馆,而每个词组、句子都是 HTML 元素。感觉在这么大个地儿找东西,像是闭着眼睛猜你想吃的冰淇淋口味一样困难。findfind_all 方法就是你的“冰淇淋味探测器”,帮你迅速定位到需要的信息。

  • find: 这个方法很像程序员早上找第一杯咖啡的习惯——快速找到并返回第一个符合条件的元素。
  • find_all: 这是更耐心、仔细的方法,它返回所有符合搜索条件的元素列表。适合在需要更多信息的情况下使用(比如一天需要多杯咖啡)。

2. 使用 find

find 方法可以在你需要迅速提取第一个符合条件的元素的时候使用。它接收各种参数,比如标签名、属性,甚至是函数。

find 方法的签名


find(name=None, attrs={}, recursive=True, string=None, **kwargs)

find 方法的参数

  • name: 你想查找的标签名。可以是任何 HTML 标签,比如 div, p, h1, a 等。
  • attrs: 标签属性字典。例如 {'class': 'example'}{'id': 'main'}。这个参数可以帮助缩小搜索范围。
  • recursive: 布尔参数,决定搜索是否在所有嵌套层级中进行。默认值是 True,即搜索所有层级。
  • string: 查找包含特定文本的元素。对按照文本内容筛选元素非常有用。
  • kwargs: 用于按属性搜索的其他参数。如果指定参数如 class_,它会被理解为 attrs={'class': 'value'}

示例

Python

from bs4 import BeautifulSoup

html_doc = """
<html>
    <head><title>The Dormouse's story</title></head>
    <body>
        <p class="title"><b>The Dormouse's story</b></p>
        <p class="story">从前有三个小妹妹;她们的名字是
        <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>、
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> 和
        <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
        她们住在一口井的底部。</p>
    </body>
</html>
"""

soup = BeautifulSoup(html_doc, 'html.parser')
first_link = soup.find('a')  # 找到第一个 <a> 标签

print(first_link)  # 输出: <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>

如你所见,find 方法找到了文档中的第一个 <a> 标签,我们已经安心继续找其他的信息了,因为必要的信息已经找到了。

3. 使用 find_all

find_all 方法返回所有符合条件的元素列表。在你需要获取某一类型的所有标签或者具有某一特定类的所有元素时特别有用。

find_all 方法的签名


find_all(name=None, attrs={}, recursive=True, string=None, limit=None, **kwargs)

find_all 方法的参数

  • name: 标签名,可以是单个标签名字符串(div, a, p 等)或者标签名列表,比如 ["div", "p"]
  • attrs: 筛选标签的属性字典,例如 {'class': 'example'}
  • recursive: 决定搜索是否递归进行,包括嵌套标签。默认值是 True
  • string: 搜索包含特定文本的标签。
  • limit: 限定返回结果的最大数量。如果设置了值,方法最多返回 limit 个元素。
  • kwargs: 用于按标签属性筛选的额外参数。

使用 find_all 的示例

find 像是从书架上快速找到一本书,而 find_all 是一个更细致的方法,比如逐个阅读所有书的章节标题来找到想要的内容。

Python

all_links = soup.find_all('a')  # 找到所有 <a> 标签

for link in all_links:
    print(link.get('href'))  # 输出链接: http://example.com/elsie, http://example.com/lacie, http://example.com/tillie

在这个例子中,我们找到了所有的 <a> 标签,然后从中提取链接。这对需要收集页面上的所有链接的场景特别有用。

重要提示! find()find_all() 方法不仅可以在 soup 对象上调用,还可以在通过 find(), select() 等方法返回的任何子元素上调用。

4. 使用属性过滤元素

现在,当我们已经渴望数据的时候,是时候变得更具体一些了。findfind_all 方法允许我们通过属性来过滤元素。这就像是调节咖啡机的过滤设置,以获得正是你想要的饮品。

Python

link_with_id = soup.find('a', id='link2')  # 找到具有 id='link2' 的 <a>

print(link_with_id.text)  # 输出: Lacie

通过使用 id 参数,我们快速找到了需要的元素。同样,也可以使用其他属性,比如 class

Python

links_with_class = soup.find_all('a', class_='sister')  # 找到所有 class='sister' 的 <a>

for link in links_with_class:
    print(link.get('id'))  # 输出: link1, link2, link3

5. 对比 findfind_all:什么时候用哪个?

了解了两种方法后,你可能会问:「该选用 find 还是 find_all?」很简单。如果你确定页面上只有一个你需要的元素,或者你只关心第一个找到的元素,选 find。如果你需要收集所有符合条件的元素,用 find_all 更合适。

参数 find find_all
返回值 返回第一个找到的元素(如果没找到返回 None 返回找到的元素列表(如果没有找到返回空列表)
用途 需要单个目标元素时 需要所有符合条件的目标元素时
limit 参数 不支持 支持:设置返回的最大数量

实例对比: 如果需要获取页面上的所有 h2 标题,使用 find_all。但如果你只需要第一个 h2 标题,用 find 就行。

Python

# 获取页面上的所有 h2 标签
all_h2_tags = soup.find_all("h2")

# 仅获取第一个 h2 标签
first_h2_tag = soup.find("h2")

6. 实践任务

现在你已经了解了理论,咱们来实战一下吧。开发一个小脚本,从博客文章中提取标题和链接。使用 find_all 方法找到所有标题和链接,假设它们位于带有 post-title 类的 <h2> 标签中。

Python

blog_html = """
<html>
  <body>
    <h2 class="post-title"><a href="http://example.com/post1">First Post</a></h2>
    <h2 class="post-title"><a href="http://example.com/post2">Second Post</a></h2>
    <h2 class="post-title"><a href="http://example.com/post3">Third Post</a></h2>
  </body>
</html>
"""

blog_soup = BeautifulSoup(blog_html, 'html.parser')
post_titles = blog_soup.find_all('h2', class_='post-title')

for post in post_titles:
    title = post.text
    link = post.find('a')['href']
    print(f"标题: {title}, 链接: {link}")

如果一切正常,你将看到:

标题: First Post, 链接: http://example.com/post1
标题: Second Post, 链接: http://example.com/post2
标题: Third Post, 链接: http://example.com/post3

注意,上面例子中方法 find() 是在 post 对象上调用的。这样可以在已经找到的元素上继续查找子元素。

7. 常见问题

当使用 findfind_all 时,经常会遇到问题。例如,find 方法如果找不到元素,将返回 None,这可能导致 AttributeError。因此在使用结果之前,建议总是检查其是否有效。

另外,拼写错误的属性是常见问题之一。如果属性拼错了,方法将无法找到任何内容。因此建议在 HTML 代码中核对属性拼写的正确性。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION