前言
我们将利用 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 文件用来做测试。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
< 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> 标签,通过输出内容来验证是否获取了第一个出现的标签。
1
2
3
4
5
|
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() 方法具体如下:
1
|
find(name,attrs,recursive,text, * * kwargs)
|
正如上代码所示,find()
方法接受五个参数:name、attrs、recursive、text 和 **kwargs 。name 、attrs 和 text 参数都可以在 find()
方法充当过滤器,提高匹配结果的精确度。
搜索标签
除了上面代码的搜索 <ul> 标签外,我们还可以搜索 <li> 标签,返回结果也是返回出现的第一个匹配内容。
1
2
3
4
|
tag_li = soup.find( 'li' )
# tag_li = soup.find(name = "li")
print type (tag_li)
print tag_li.div.string
|
搜索文本
如果我们只想根据文本内容来搜索的话,我们可以只传入文本参数 :
1
2
3
|
search_for_text = soup.find(text = 'plants' )
print type (search_for_text)
< class 'bs4.element.NavigableString' >
|
返回的结果也是 NavigableString 对象 。
根据正则表达式搜索
如下的一段 HTML 文本内容
1
2
3
4
|
<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 邮件地址并没有包括在任何标签内,这样就不能根据标签来找到邮件地址了。这个时候,我们可以使用正则表达式来进行匹配。
1
2
3
4
5
6
7
8
9
10
11
12
|
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
|
在使用正则表达式进行匹配时,如果有多个匹配项,也是先返回第一个。
根据标签属性值搜索
可以通过标签的属性值来搜索:
1
2
|
search_for_attribute = soup.find( id = 'primaryconsumers' )
print search_for_attribute.li.div.string
|
根据标签属性值来搜索对大多数属性都是可用的,例如:id、style 和 title 。
但是对以下两种情况会有不同:
- 自定义属性
- 类 ( class ) 属性
我们不能再直接使用属性值来搜索了,而是得使用 attrs 参数来传递给 find()
函数。
根据自定义属性来搜索
在 HTML5 中是可以给标签添加自定义属性的,例如给标签添加 属性。
如下代码所示,如果我们再像搜索 id 那样进行操作的话,会报错的,Python 的变量不能包括 - 符号。
1
2
3
4
5
6
|
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 属性值来传递一个字典类型作为参数进行搜索:
1
2
|
using_attrs = customsoup.find(attrs = { 'data-custom' : 'custom' })
print using_attrs
|
基于 CSS 中的 类 进行搜索
对于 CSS 的类属性,由于在 Python 中 class 是个关键字,所以是不能当做标签属性参数传递的,这种情况下,就和自定义属性一样进行搜索。也是使用 attrs 属性,传递一个字典进行匹配 。
除了使用 attrs 属性之外,还可以使用 class_ 属性进行传递,这样与 class 区别开了,也不会导致错误。
1
2
3
4
|
css_class = soup.find(attrs = { 'class' : 'producerlist' })
css_class2 = soup.find( class_ = "producerlist" )
print css_class
print css_class2
|
使用自定义的函数搜索
可以给 find()
方法传递一个函数,这样就会根据函数定义的条件进行搜索。
函数应该返回 true 或者是 false 值。
1
2
3
4
|
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 提供了各种搜索方法,同样,我们也可以联合使用这些方法来进行匹配,提高搜索的准确度。
1
2
3
4
5
6
7
8
9
10
11
|
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()
中 。
1
2
3
4
5
|
# 搜索所有 class 属性等于 tertiaryconsumerlist 的标签。
all_tertiaryconsumers = soup.find_all( class_ = 'tertiaryconsumerlist' )
print type (all_tertiaryconsumers)
for tertiaryconsumers in all_tertiaryconsumers:
print tertiaryconsumers.div.string
|
find_all()
方法为 :
1
|
find_all(name,attrs,recursive,text,limit, * * kwargs)
|
它的参数和 find()
方法有些类似,多个了 limit 参数。limit 参数是用来限制结果数量的。而 find()
方法的 limit 就是 1 了。
同时,我们也能传递一个字符串列表的参数来搜索标签、标签属性值、自定义属性值和 CSS 类。
1
2
3
4
5
6
7
8
|
# 搜索所有的 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()
方法类似。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 搜索 父标签
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()
函数能够搜索同一级的下一个标签。
1
2
3
|
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()
将会返回所有下级的标签项。
1
2
3
4
|
# 搜索下一级标签
first_div = soup.div
all_li_tags = first_div.find_all_next( "li" )
print all_li_tags
|
搜索上一个标签
与搜索下一个标签类似,使用 find_previous()
和 find_all_previous()
方法来搜索上一个标签。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:http://www.glumes.com/python-beautifulsoup-search-data/