1篙骡、find_all
find_all( name , attrs , recursive , string , **kwargs )
find_all()
方法搜索當(dāng)前tag的所有tag子節(jié)點(diǎn),并判斷是否符合過(guò)濾器的條件:
soup.find_all("title")
# [<title>The Dormouse's story</title>]
soup.find_all("a")
# [<a class="sister" id="link1">Elsie</a>,
# <a class="sister" id="link2">Lacie</a>,
# <a class="sister" id="link3">Tillie</a>]
soup.find_all(id="link2")
# [<a class="sister" id="link2">Lacie</a>]
import re
# 模糊查詢 包含sisters的就可以
soup.find(string=re.compile("sisters"))
# 'Once upon a time there were three little sisters; and their names were\n'
有幾個(gè)方法很相似,還有幾個(gè)方法是新的,參數(shù)中的 string
和 id
是什么含義? 為什么 find_all("p", "title")
返回的是CSS Class為”title”的<p>標(biāo)簽? 我們來(lái)仔細(xì)看一下 find_all()
的參數(shù).
1.1 name 參數(shù)
name
參數(shù)可以查找所有名字為 name
的tag,字符串對(duì)象會(huì)被自動(dòng)忽略掉.
簡(jiǎn)單的用法如下:
soup.find_all("title")
# [<title>The Dormouse's story</title>]
搜索 name
參數(shù)的值可以使任一類型的 過(guò)濾器 ,字符串,正則表達(dá)式,列表,方法或是 True
.
<1> 傳字符串
最簡(jiǎn)單的過(guò)濾器是字符串.在搜索方法中傳入一個(gè)字符串參數(shù),Beautiful Soup會(huì)查找與字符串完整匹配的內(nèi)容,下面的例子用于查找文檔中所有的<b>標(biāo)簽
soup.find_all('b')
# [<b>The Dormouse's story</b>]
<2> 傳正則表達(dá)式
如果傳入正則表達(dá)式作為參數(shù),Beautiful Soup會(huì)通過(guò)正則表達(dá)式的 match()
來(lái)匹配內(nèi)容.下面例子中找出所有以b開(kāi)頭的標(biāo)簽,這表示<body>和<b>標(biāo)簽都應(yīng)該被找到
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
# body
# b
<3> 傳列表
如果傳入列表參數(shù),Beautiful Soup會(huì)將與列表中任一元素匹配的內(nèi)容返回.下面代碼找到文檔中所有<a>標(biāo)簽和<b>標(biāo)簽
soup.find_all(["a", "b"])
# [<b>The Dormouse's story</b>,
# <a class="sister" id="link1">Elsie</a>,
# <a class="sister" id="link2">Lacie</a>,
# <a class="sister" id="link3">Tillie</a>]
1.2 keyword 參數(shù)
如果一個(gè)指定名字的參數(shù)不是搜索內(nèi)置的參數(shù)名,搜索時(shí)會(huì)把該參數(shù)當(dāng)作指定名字tag的屬性來(lái)搜索,如果包含一個(gè)名字為 id
的參數(shù),Beautiful Soup會(huì)搜索每個(gè)tag的”id”屬性.
soup.find_all(id='link2')
# [<a class="sister" id="link2">Lacie</a>]
import re
# 超鏈接包含elsie標(biāo)簽
print(soup.find_all(href=re.compile("elsie")))
# [<a class="sister" id="link1">Elsie</a>]
# 以The作為開(kāi)頭的字符串
print(soup.find_all(text=re.compile("^The")))
# ["The Dormouse's story", "The Dormouse's story"]
# class選擇器包含st的節(jié)點(diǎn)
print(soup.find_all(class_=re.compile("st")))
搜索指定名字的屬性時(shí)可以使用的參數(shù)值包括 字符串 , 正則表達(dá)式 , 列表, True .
下面的例子在文檔樹(shù)中查找所有包含 id
屬性的tag,無(wú)論 id
的值是什么:
soup.find_all(id=True)
# [<a class="sister" id="link1">Elsie</a>,
# <a class="sister" id="link2">Lacie</a>,
# <a class="sister" id="link3">Tillie</a>]
使用多個(gè)指定名字的參數(shù)可以同時(shí)過(guò)濾tag的多個(gè)屬性:
soup.find_all(href=re.compile("elsie"), id='link1')
# [<a class="sister" id="link1">three</a>]
在這里我們想用 class 過(guò)濾宴胧,不過(guò) class 是 python 的關(guān)鍵詞途茫,這怎么辦削葱?加個(gè)下劃線就可以
print(soup.find_all("a", class_="sister"))
'''
[<a class="sister" id="link1">Elsie</a>,
<a class="sister" id="link2">Lacie</a>,
<a class="sister" id="link3">Tillie</a>
]
'''
通過(guò) find_all()
方法的 attrs
參數(shù)定義一個(gè)字典參數(shù)來(lái)搜索包含特殊屬性的tag:
data_soup.find_all(attrs={"data-foo": "value"})
# [<div data-foo="value">foo!</div>]
注意:如何查看條件id和class同時(shí)存在時(shí)的寫法
print(soup.find_all('b', class_="story", id="x"))
print(soup.find_all('b', attrs={"class":"story", "id":"x"}))
1.3 text 參數(shù)
通過(guò) text
參數(shù)可以搜搜文檔中的字符串內(nèi)容.與 name
參數(shù)的可選值一樣, text
參數(shù)接受 字符串 , 正則表達(dá)式 , 列表, True
import re
print(soup.find_all(text="Elsie"))
# ['Elsie']
print(soup.find_all(text=["Tillie", "Elsie", "Lacie"]))
# ['Elsie', 'Lacie', 'Tillie']
# 只要包含Dormouse就可以
print(soup.find_all(text=re.compile("Dormouse")))
# ["The Dormouse's story", "The Dormouse's story"]
1.4 limit 參數(shù)
find_all()
方法返回全部的搜索結(jié)構(gòu),如果文檔樹(shù)很大那么搜索會(huì)很慢.如果我們不需要全部結(jié)果,可以使用 limit
參數(shù)限制返回結(jié)果的數(shù)量.效果與SQL中的limit關(guān)鍵字類似,當(dāng)搜索到的結(jié)果數(shù)量達(dá)到 limit
的限制時(shí),就停止搜索返回結(jié)果.
print(soup.find_all("a",limit=2))
print(soup.find_all("a")[0:2])
'''
[<a class="sister" id="link1">Elsie</a>,
<a class="sister" id="link2">Lacie</a>]
'''
2半抱、find()
find( name , attrs , recursive , string , **kwargs )
find_all()
方法將返回文檔中符合條件的所有tag,盡管有時(shí)候我們只想得到一個(gè)結(jié)果.比如文檔中只有一個(gè)<body>標(biāo)簽,那么使用 find_all()
方法來(lái)查找<body>標(biāo)簽就不太合適, 使用 find_all
方法并設(shè)置 limit=1
參數(shù)不如直接使用 find()
方法.下面兩行代碼是等價(jià)的:
soup.find_all('title', limit=1)
# [<title>The Dormouse's story</title>]
soup.find('title')
# <title>The Dormouse's story</title>
唯一的區(qū)別是 find_all()
方法的返回結(jié)果是值包含一個(gè)元素的列表,而 find()
方法直接返回結(jié)果.
find_all()
方法沒(méi)有找到目標(biāo)是返回空列表, find()
方法找不到目標(biāo)時(shí),返回 None
.
print(soup.find("nosuchtag"))
# None
soup.head.title
是 tag的名字 方法的簡(jiǎn)寫.這個(gè)簡(jiǎn)寫的原理就是多次調(diào)用當(dāng)前tag的 find()
方法:
soup.head.title
# <title>The Dormouse's story</title>
soup.find("head").find("title")
# <title>The Dormouse's story</title>