Python Beautiful Soup 搜索功能详解:从基础到高级用法

Owen
Owen
发布时间:2026-10-13| 5人浏览过
原创

本文深入解析 Python Beautiful Soup 库的搜索功能,涵盖 find() 与 find_all() 的核心用法。详细讲解如何通过标签名、属性、文本及正则表达式精准定位元素,并演示处理自定义属性和 CSS 类属性的技巧。此外,还介绍了利用父级、同级及下级标签进行关联搜索的高级策略,帮助开发者高效提取网页数据。

前言

本文将介绍如何利用 Beautiful Soup 模块强大的搜索功能,依据标签名称、属性、文档文本以及正则表达式来精准定位和提取网页内容。

搜索方法概览

Beautiful Soup 内置了一系列高效的搜索方法,主要包括:

  • find()
  • find_all()
  • find_parent()
  • find_parents()
  • find_next_sibling()
  • find_next_siblings()
  • find_previous_sibling()
  • find_previous_siblings()
  • find_previous()
  • find_all_previous()
  • find_next()
  • find_all_next()

使用 find() 方法进行搜索

为了演示搜索过程,我们首先需要构建一个用于测试的 HTML 文件。

<html>
<body>
<div class="ecopyramid">
 <ul id="producers">
 <li class="producerlist">
  <div class="name">plants</div>
  <div class="number">100000</div>
 </li>
 <li class="producerlist">
  <div class="name">algae</div>
  <div class="number">100000</div>
 </li>
 </ul>
 <ul id="primaryconsumers">
 <li class="primaryconsumerlist">
  <div class="name">deer</div>
  <div class="number">1000</div>
 </li>
 <li class="primaryconsumerlist">
  <div class="name">rabbit</div>
  <div class="number">2000</div>
 </li>
 </ul>
 <ul id="secondaryconsumers">
 <li class="secondaryconsumerlist">
  <div class="name">fox</div>
  <div class="number">100</div>
 </li>
 <li class="secondaryconsumerlist">
  <div class="name">bear</div>
  <div class="number">100</div>
 </li>
 </ul>
 <ul id="tertiaryconsumers">
 <li class="tertiaryconsumerlist">
  <div class="name">lion</div>
  <div class="number">80</div>
 </li>
 <li class="tertiaryconsumerlist">
  <div class="name">tiger</div>
  <div class="number">50</div>
 </li>
 </ul>
</div>
</body>
</html>

通过 find() 方法,我们可以获取 <ul> 标签,默认情况下该方法返回第一个匹配到的元素。随后,我们继续获取 <li> 标签,同样默认返回首个匹配项,最后获取 <div> 标签,并通过输出内容来验证是否成功获取了第一个出现的标签组合。

from bs4 import BeautifulSoup
with open('search.html','r') as filename:
 soup = BeautifulSoup(filename,'lxml')
first_ul_entries = soup.find('ul')
print first_ul_entries.li.div.string

find() 方法的具体定义如下:

find(name,attrs,recursive,text,**kwargs) 

如上代码所示,find() 方法接收五个参数:name、attrs、recursive、text 以及 **kwargs。其中,name、attrs 和 text 参数均可作为 find() 方法的过滤器使用,从而显著提升匹配结果的精确度。

搜索标签

除了上述搜索 <ul> 标签的示例外,我们还可以搜索 <li> 标签,其返回结果同样仅包含第一个匹配到的内容。

tag_li = soup.find('li')
# tag_li = soup.find(name = "li")
print type(tag_li)
print tag_li.div.string

搜索文本

如果希望仅根据文本内容进行搜索,可以直接传入文本参数:

search_for_text = soup.find(text='plants')
print type(search_for_text)
<class 'bs4.element.NavigableString'>

此时返回的结果类型为 NavigableString 对象。

根据正则表达式搜索

参考以下 HTML 文本片段:

<div>The below HTML has the information that has email ids.</div>
 abc@example.com 
<div>xyz@example.com</div> 
 <span>foo@example.com</span>

可以看到,邮件地址 abc@example 并未被包裹在任何标签内,因此无法直接通过标签名称来定位它。此时,我们可以借助正则表达式进行匹配。

email_id_example = """
 <div>The below HTML has the information that has email ids.</div>
 abc@example.com
 <div>xyz@example.com</div>
 <span>foo@example.com</span>
 """
email_soup = BeautifulSoup(email_id_example,'lxml')
print email_soup
# pattern = "\w+@\w+\.\w+"
emailid_regexp = re.compile("\w+@\w+\.\w+")
first_email_id = email_soup.find(text=emailid_regexp)
print first_email_id

在使用正则表达式进行匹配时,若存在多个匹配项,方法仍会优先返回第一个结果。

根据标签属性值搜索

我们可以通过标签的属性值来进行搜索:

search_for_attribute = soup.find(id='primaryconsumers')
print search_for_attribute.li.div.string

这种基于属性值的搜索方式适用于大多数标准属性,例如 id、style 和 title。

然而,针对以下两种特殊情况,处理方式会有所不同:

  • 自定义属性
  • CSS 类 ( class ) 属性

在这两种情况下,我们不能直接通过属性名搜索,而必须使用 attrs 参数将其传递给 find() 函数。

根据自定义属性搜索

在 HTML5 标准中,允许为标签添加自定义属性,例如为标签添加特定属性。

如下代码所示,如果我们尝试像搜索 id 那样直接操作,将会引发报错,因为 Python 的变量名中不能包含连字符(-)。

customattr = """
 <p data-custom="custom">custom attribute example</p>
   """
customsoup = BeautifulSoup(customattr,'lxml')
customsoup.find(data-custom="custom")
# SyntaxError: keyword can't be an expression

此时,应使用 attrs 属性传递一个字典作为参数来进行搜索:

using_attrs = customsoup.find(attrs={'data-custom':'custom'})
print using_attrs

基于 CSS 中的 class 进行搜索

对于 CSS 的 class 属性,由于 class 是 Python 的关键字,因此不能直接作为标签属性参数传递。在这种情况下,处理方式与自定义属性类似,需使用 attrs 属性并传递字典进行匹配。

除了使用 attrs 属性外,还可以使用 class_ 属性进行传递,这样既与 class 关键字区分开,又能避免语法错误。

css_class = soup.find(attrs={'class':'producerlist'})
css_class2 = soup.find(class_ = "producerlist")
print css_class
print css_class2

使用自定义函数搜索

可以向 find() 方法传递一个自定义函数,从而根据函数定义的条件进行搜索。

该函数应当返回布尔值 true 或 false。

def is_producers(tag):
 return tag.has_attr('id') and tag.get('id') == 'producers'
tag_producers = soup.find(is_producers)
print tag_producers.li.div.string

代码中定义了一个 is_producers 函数,用于检查标签是否具有 id 属性且其值等于 'producers',若符合条件则返回 true,否则返回 false。

联合使用各种搜索方法

Beautiful Soup 提供了丰富的搜索方法,我们可以将这些方法联合使用,以进一步提高搜索的准确度。

combine_html = """
 <p class="identical">
  Example of p tag with class identical
 </p>
 <div class="identical">
  Example of div tag with class identical
 <div>
 """
combine_soup = BeautifulSoup(combine_html,'lxml')
identical_div = combine_soup.find("div",class_="identical")
print identical_div

使用 find_all() 方法进行搜索

使用 find() 方法会从搜索结果中返回第一个匹配的内容,而 find_all() 方法则会返回所有匹配的项。

在 find() 方法中使用的过滤项,同样可以应用于 find_all() 方法。事实上,这些过滤项可应用于任何搜索方法中,例如 find_parents() 和 find_siblings()。

# 搜索所有 class 属性等于 tertiaryconsumerlist 的标签。
all_tertiaryconsumers = soup.find_all(class_='tertiaryconsumerlist')
print type(all_tertiaryconsumers)
for tertiaryconsumers in all_tertiaryconsumers:
 print tertiaryconsumers.div.string

find_all() 方法的定义为:

find_all(name,attrs,recursive,text,limit,**kwargs)

其参数与 find() 方法类似,但多了一个 limit 参数。limit 参数用于限制返回结果的数量,而 find() 方法的 limit 值默认为 1。

同时,我们也可以传递字符串列表作为参数,以搜索特定的标签、标签属性值、自定义属性值或 CSS 类。

# 搜索所有的 div 和 li 标签
div_li_tags = soup.find_all(["div","li"])
print div_li_tags
print
# 搜索所有类属性是 producerlist 和 primaryconsumerlist 的标签
all_css_class = soup.find_all(class_=["producerlist","primaryconsumerlist"])
print all_css_class
print

搜索相关标签

通常情况下,我们可以使用 find() 和 find_all() 方法来搜索指定标签,同时也能搜索与这些标签相关的其他感兴趣标签。

搜索父标签

可以使用 find_parent() 或者 find_parents() 方法来搜索标签的父标签。

find_parent() 方法将返回第一个匹配的内容,而 find_parents() 将返回所有匹配的内容,这一点与 find() 和 find_all() 方法类似。

# 搜索 父标签
primaryconsumers = soup.find_all(class_='primaryconsumerlist')
print len(primaryconsumers)
# 取父标签的第一个
primaryconsumer = primaryconsumers[0]
# 搜索所有 ul 的父标签
parent_ul = primaryconsumer.find_parents('ul')
print len(parent_ul)
# 结果将包含父标签的所有内容
print parent_ul
print
# 搜索,取第一个出现的父标签.有两种操作
immediateprimary_consumer_parent = primaryconsumer.find_parent()
# immediateprimary_consumer_parent = primaryconsumer.find_parent('ul')
print immediateprimary_consumer_parent

搜索同级标签

Beautiful Soup 还提供了搜索同级标签的功能。

使用 find_next_siblings() 函数能够搜索同一级别的下一个所有标签,而 find_next_sibling() 函数能够搜索同一级别的下一个标签。

producers = soup.find(id='producers')
next_siblings = producers.find_next_siblings()
print next_siblings

同样,也可以使用 find_previous_siblings() 和 find_previous_sibling() 方法来搜索上一个同级的标签。

搜索下一个标签

使用 find_next() 方法将搜索下一个标签中第一个出现的,而 find_next_all() 将会返回所有下级的标签项。

# 搜索下一级标签
first_div = soup.div
all_li_tags = first_div.find_all_next("li")
print all_li_tags

搜索上一个标签

与搜索下一个标签类似,使用 find_previous() 和 find_all_previous() 方法来搜索上一个标签。

总结

以上就是本文的全部内容,希望这些内容能对大家学习或使用 Python 有所帮助。如有任何疑问,欢迎留言交流,感谢大家对本站的支持。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。