Python Beautiful Soup 搜索功能详解:从基础到高级用法
本文深入解析 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 有所帮助。如有任何疑问,欢迎留言交流,感谢大家对本站的支持。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













