Learn Beautiful Soup(3)——使用Beautiful Soup进行查找

            网页中有用的信息一般存在于网页中的文本或各类不一样标签的属性值,为了得到这些网页信息,有必要有一些查找方法能够获取这些文本值或标签属性。而Beautiful Soup中内置了一些查找方式:css

  •            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

<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>
	</body>
</html>


以上代码是一个生态金字塔的简单展现,为了找到其中的第一辈子产者,第一消费者或第二消费者,咱们可使用Beautiful Soup的查找方法。通常来讲,为了找到BeautifulSoup对象内任何第一个标签入口,咱们可使用find()方法。python

找到第一辈子产者

能够明显看到,生产者在第一个<ul>标签里,由于生产者是在整个HTML文档中第一个<ul>标签中出现,因此能够简单的使用find()方法找到第一辈子产者。下图HTML树表明了第一个生产者所在位置。正则表达式

而后在ecologicalpyramid.py中写入下面一段代码,使用ecologicalpyramid.html文件建立BeautifulSoup对象。函数

from bs4 import BeautifulSoup
with open("ecologicalpyramid.html","r") as ecological_pyramid:
soup = BeautifulSoup(ecological_pyramid)
producer_entries = soup.find("ul")
print(producer_entries.li.div.string)


 输出获得:plantsspa


find()说明

find()函数以下:code

find(name,attrs,recursive,text,**wargs)regexp

这些参数至关于过滤器同样能够进行筛选处理。orm

不一样的参数过滤能够应用到如下状况:xml

  • 查找标签,基于name参数
  • 查找文本,基于text参数
  • 基于正则表达式的查找
  • 查找标签的属性,基于attrs参数
  • 基于函数的查找

 经过标签查找

咱们能够传递任何标签的名字来查找到它第一次出现的地方。找到后,find函数返回一个BeautifulSoup的标签对象。

from bs4 import BeautifulSoup

with open("ecologicalpyramid.html", "r") as ecological_pyramid:
	soup = BeautifulSoup(ecological_pyramid,"html")
producer_entries = soup.find("ul")
print(type(producer_entries))

输出的获得 <class 'bs4.element.Tag'>

经过文本查找

直接字符串的话,查找的是标签。若是想要查找文本的话,则须要用到text参数。以下所示:

from bs4 import BeautifulSoup

with open("ecologicalpyramid.html", "r") as ecological_pyramid:
	soup = BeautifulSoup(ecological_pyramid,"html")
plants_string = soup.find(text="plants")
print(plants_string)

输出:plants

经过正则表达式查找

有如下HTML代码:

<br/>
<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>

若是想找出第一个邮箱地址,可是因为第一个邮箱地址没有标签包含,因此经过其余方式很难找到。可是咱们能够把邮箱地址进行正则表达式处理,这样就容易多了。

参考以下代码:

import re
from bs4 import BeautifulSoup

email_id_example = """<br/>
<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>
"""

soup = BeautifulSoup(email_id_example)
emailid_regexp = re.compile("\w+@\w+\.\w+")
first_email_id = soup.find(text=emailid_regexp)
print(first_email_id)

输出:abc@example.com

经过标签属性进行查找

观看例程HTML代码,其中第一消费者在ul标签里面且id属性为priaryconsumers.

由于第一消费者出现的ul不是文档中第一个ul,因此经过前面查找标签的办法就行不通了。如今经过标签属性进行查找,参考代码以下:

from bs4 import BeautifulSoup

with open("ecologicalpyramid.html", "r") as ecological_pyramid:
	soup = BeautifulSoup(ecological_pyramid,"html")
primary_consumer = soup.find(id="primaryconsumers")
print(primary_consumer.li.div.string)

输出:deer

经过标签属性查找的方式适用于大多数标签属性,包括id,style,title,可是有一组标签属性例外。

  • Custom attrbutes
  • Class
此时,咱们须要借助attrs参数来进行传递。

基于定制属性的查找


好比咱们HTML5标签中的data-custom属性,若是咱们这样
customattr = ""'<p data-custom="custom">custom attribute 
example</p>"""
customsoup = BeautifulSoup(customattr,'lxml')
customSoup.find(data-custom="custom")

那么则会报错。缘由是在Python中变量不能呢含有-这个字符,而咱们传递的data-custom有-这个字符。
解决的办法是在attrs属性用字典进行传递参数。
using_attrs = customsoup.find(attrs={'data-custom':'custom'})
print(using_attrs)

基于CSS类的查找


由于class是Python的保留关键字,因此没法使用class这个关键字。因此解决办法相似上面。
css_class = soup.find(attrs={'class':'primaryconsumerlist'})
print(css_class)

还有另外一个办法。BeautifulSoup有一个特别的关键字参数class_。示例:
方法1:
css_class = soup.find(class_ = "primaryconsumers" )

方法2:
css_class = soup.find(attrs={'class':'primaryconsumers'})

基于定义的函数进行查找

能够传递函数到find()来基于函数定义的条件进行查找。函数值必须返回true或者false。
例子:
def is_secondary_consumers(tag):
return tag.has_attr('id') and tag.get('id') == 
'secondaryconsumers'
secondary_consumer = soup.find(is_secondary_consumers)
print(secondary_consumer.li.div.string)

输出:fox

把方法进行组合后进行查找


能够用其中任何方法进行组合来进行查找,好比同时基于标签名和id号。

使用find_all查找

find()用来查找第一个匹配结果出现的地方,而find_all()正如名字所示,将会找到全部匹配结果出现的地方。应用到find()中的不一样过滤参数同理能够用到find_all()中,实际上,过滤参数能够用于任何查找函数,如find_parents()或和find_siblings()。

查找全部三级消费者

all_tertiaryconsumers = 
soup.find_all(class_="tertiaryconsumerslist")

其all_tertiaryconsumers的类型是列表。
因此咱们对其列表进行迭代,循环输出三级消费者的名字。
for tertiaryconsumer in all_tertiaryconsumers:
print(tertiaryconsumer.div.string)

输出:
lion
tiger

理解用于find_all()的参数


相比find(),find_all()有个额外的参数limit,以下所示:
find_all(name,attrs,recursive,text,limit,**kwargs)
limit参数能够限制咱们想要获得结果的数目。参照前面的邮件地址例子,咱们能够获得全部右键地址经过:
email_ids = soup.find_all(text=emailid_regexp)
print(email_ids)

输出:[u'abc@example.com',u'xyz@example.com',u'foo@example.com']

当咱们使用limit参数,效果以下:
email_ids_limited = soup.find_all(text=emailid_regexp,limit=2)
print(email_ids_limited)

限制获得两个结果,因此输出为:
[u'abc@example.com',u'xyz@example.com']

说白了,find()也就是当limit=1时的find_all()。

能够向find函数传递True或False参数,若是咱们传递True给find_all(),则返回全部soup对象的标签。对于find()来讲,则返回第一个标签。
举例查找文本,传递True将会返回全部文本。
all_texts = soup.find_all(text=True)
print(all_texts)

输出:
[u'\n', u'\n', u'\n', u'\n', u'\n', u'plants', u'\n', u'100000', 
u'\n', u'\n', u'\n', u'algae', u'\n', u'100000', u'\n', u'\n', 
u'\n', u'\n', u'\n', u'deer', u'\n', u'1000', u'\n', u'\n', 
u'\n', u'rabbit', u'\n', u'2000', u'\n', u'\n', u'\n', 
u'\n', u'\n', u'fox', u'\n', u'100', u'\n', u'\n', u'\n', 
u'bear', u'\n', u'100', u'\n', u'\n', u'\n', u'\n', 
u'\n', u'lion', u'\n', u'80', u'\n', u'\n', u'\n', 
u'tiger', u'\n', u'50', u'\n', u'\n', u'\n', u'\n', 
u'\n'] 

一样的,咱们能够在传递text参数时传递一个字符串列表,那么find_all()会找到诶个在列表中定义过的字符串。
all_texts_in_list = soup.find_all(text=["plants","algae"])
print(all_texts_in_list)

输出:
[u'plants', u'algae']

这个一样适用于查找标签,标签属性,定制属性和CSS类。如:
div_li_tags = soup.find_all(["div","li"])

find()和find_all()都会查找一个对象全部后辈们,不过咱们能够控制它经过recursive参数。若是recursive=False,那么超找只会找到该对象的最近后代。

经过标签之间的关系进行查找

咱们能够经过find()和find_all()来查找到想要内容。但有时候,咱们须要查看的与以内容相关先前的标签或者后面的标签来获取额外的信息。好比方法find_parents()和find_next_siblings()等等。通常的,在find()和find_all()方法后使用上述方法,由于find()和find_all()能够找到特殊的一个标签,而后咱们能够经过这个特殊的标签找到其余的想要的与之有关系的标签。

查找父标签

经过find_parents()或find_parent()。它们之间的不一样就相似于find()和find_all()的区别。find_parents()返回所有的相匹配的父标签,而find_paret()返回最近的一个父标签。适用于find()的方法一样也使用于这两个方法。

在前面的第一消费者例子中,咱们能够找到离Primaryconsumer最近的ul父标签。
primaryconsumers = soup.find_all(class_="primaryconsumerlist")
primaryconsumer = primaryconsumers[0]
parent_ul = primaryconsumer.find_parents('ul')
print(parent_ul)

一个简单的找到一个标签的父标签的方法就是使用find_parent()却不带任何参数。
immediateprimary_consumer_parent = primary_consumer.find_parent()

查找同胞


若是标签在同一个等级的话,咱们能够说这些标签是同胞的关系,好比参照上面金字塔例子,全部ul标签就是同胞的关系。


上图ul标签下的producers,primaryconsumers,secondaryconsumers,teriaryconsumers就是同胞关系。
再看下面这个图:


div下的plants和algae不是同胞关系,可是plants和临近的number是同胞关系。
Beautiful Soup自带有查找同胞的方法。
好比find_next_siblings()和find_next_sibling()查找对象下面的同胞。举例:
producers= soup.find(id='producers')
next_siblings = producers.find_next_siblings()
print(next_siblings)

将会输出与之临近的下面的全部同胞HTML代码。

查找下一个

对每个标签来讲,下一个元素可能会是定位字符串,标签对象或者其余BeautifulSoup对象。咱们定义下一个元素为与当前元素最靠近的元素。这个不一样于同胞定义。咱们有方法能够找到咱们想要标签的下一个其余元素对象。find_all_next()找到与当前元素靠近的全部对象。而find_next()找到离当前元素最接近的对象。

好比,找到在第一个div标签后的全部li标签
first_div = soup.div
all_li_tags = first_div.find_all_next("li")

输出“:
[<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>, <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>, <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>, <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>]

查找上一个

与查找下一个相反的是查找前一个。同理用于find_all_previous()和find_all_previous()
相关文章
相关标签/搜索