Python3爬蟲神器BeautifulSoup(三)——搜索文檔樹

搜索文檔樹里面主要講find()以及find_all()的用法。在講這兩個用法之前先來說說過濾器,什么過濾器呢?顧名思義,過濾器就是按照條件過濾掉不符合的,留下符合的。那么在Python中這些條件可以是什么呢?我們來依次介紹????

1.字符串(這個沒什么好講的)

2.正則表達式(不知道的可以百度一下什么意思)

3.列表:如果傳入列表參數(shù),Beautiful Soup會將與列表中任一元素匹配的內(nèi)容返回.

4.True:True可以匹配任何值

再來說說方法,什么時候用這個方法呢?當你沒有合適的過濾器的時候,那便可以定義一個方法,方法只接受一個元素,如果返回True那么表示當前元素與之匹配并且被找到,反之將會返回false

你可以定義一個尋找包含class但是不包含id的標簽

def has_class_but_no_id(tag):

? ? return tag.has_attr('class') and not tag.has_attr('id')


好了可以來講講find_all()和find()了


先來說說.find_all(),它的具體使用規(guī)則如下

.find_all(tag,attributes,recursive,text,limit,keywords)

雖然這里有這么多個參數(shù)但是其實我們絕大多數(shù)時候只使用前兩個參數(shù)

那么我們一一介紹一下這些參數(shù)

tag:就是之前講的標簽名(像<h1>什么之類的),你可以傳入一個標簽名或者多個 標簽組成的列表

attributes:是一個用python字典封裝的一個標簽的若干屬性以及其值,例如:.find_all("span",{"class":{"green","red"}})這就可以找出所有class為green和red的span標簽

recursive:是一個遞歸參數(shù),他是一個布爾變量如果設為True那么會根據(jù)要求查找所有子標簽以及子標簽的子標簽,如果設為False那么只會查找文檔的一級標簽。當然他的默認值是True。一般我們也用不到去修改它。

text:他和attributes有點像但又很是不同,他是用標簽里面的文本去匹配而不是標簽的屬性

limit:只適用于find_all()方法,你可以指定有多少項結果返回過來,要注意的是,設置了limit后返回的是按照順序返回的,不一定是你想要的結果。

keyword:可以讓你選擇那些具有指定屬性的標簽,例如:.find_all(id = "text")這個可以找出所有id=text的標簽

但是要記住,不要濫用keyword,keyword只是BeautifulSoup中的一個冗余功能,雖然在有些場景下它顯得特別有用,但是任何能夠用keyword解決的問題都可以用其他方式解決,

就上一個例子來說

和.find_all("",{"id":"text"})是完全一樣的

接下來我們會來說說keyword的一些“缺點”

我們知道class是Python中的一個保留字,是不能當做變量名來使用的。但是HTML標簽中經(jīng)常會有class的屬性這時候.find_all(class = "green")就么沒有用了。你可以用以下方法解決

.find_all(class_="green")來代替,也就是在class后面加一個_(下劃線),但是這個方法顯得有點臃腫

我們完全可以用以下方法來代替.find_all("", {"class":"green"})

再順便說一下,用標簽參數(shù)將tag以列表的形式傳入是或關系的過濾器而keyword的與的選擇器

再來說說.find,.find其實就是.find_all()的一種特殊情況,也就是limit = 1的特殊情況。而.find_all()方法是返回一個列表而find方法是直接返回結果

.find_all()和.find只會去搜索子孫節(jié)點,如果要搜尋父節(jié)點的話那就要用.find_parents()和.find_parent()這個兩個的參數(shù)和.find_all()和.find()的一樣。其中.find_parents()和.parents功效相似,.find_parent()和.parent功效相似。BeautifulSoup還有一些其他的搜索API其中一半是和find()的參數(shù)一樣一半是和.find_all()的參數(shù)一樣,

其他的幾個分別是(中括號中的是與之功效相似的):

.find_next_siblings()[.next_siblings],.find_next_sibling()[.next_sibling],.find_previous_siblings()[.previous_siblings],.find_previous_sibling()[.previous_sibling],.find_all_next()[.next_elements],.find_next()[.next_element],.find_all_previous()[.previous_elements],.find_previous()[.previous_elements]


CSS選擇器

BeautifulSoup對象支持絕大多數(shù)CSS選擇器,在Tag和BeautifulSoup對象的.select()方法中傳入字符串參數(shù)就可以找到相應的tag(返回結果一般是列表的形式)那么我們就來說說它的使用方法。

1.可以直接通過標簽選擇:

? ? ? ? ? ? ? ? 例如(還是以第二篇的那個HTML為例子):

? ? ? ? ? ? ? ? ? ? ????????soup.select("title")

????????????????????????????那么就可以得到以下結果:[<title>The Dormouse's story</title>],通過這個方法可以得到所有title標簽

????????????????也可以用這個語法:

???????????????????????????? soup.select("p:nth-of-type(3)")

? ? ? ? ? ? ? ? ? ? ? ? ? ? 那么就可以得到以下的結果:[<p class = "story">....</p>]

????????????????????????????在這個例子中p:nth-of-type(3)這條語法相當于是選擇第三個p標簽,相當于soup.select(p)[2])

? ? ? ? ? ? ? ? 我們也可以通過tag逐層尋找:

????????????????????????????soup.select("body a")這方法可以找到body下所有的a標簽

? ? ? ? ? ? ? ? ? ? ? ? ? ? 也可以用這個soup.select("body > a")(這里的body和>和a之間一定要有空格)這個方法的話可以得到的是body下屬的第一個a標簽

? ? ? ? ? ? ? ? 也可以來組合一下:

? ? ? ? ? ? ? ? ????????????soup.select("p > a:nth-of-type(2)")

? ? ? ? ? ? ? ? 當然也會有尋找兄弟節(jié)點的方法:

? ? ? ? ? ? ? ? ? ? ? ? ? ? soup.select("#link1 ~ .mysis")這個方法可以找到id = link1后的所有兄弟節(jié)點標簽

? ? ? ? ? ? ? ? ? ? ? ? ? ? 而這個方法soup.select("#link1 + .mysis")是可以得到id = link1的下一個兄弟標簽

2.我們也可以通過類名來尋找

? ? ? ? ? ? ? ? 例如:

????????????????????????????soup.select(".story")這個方法可以找到所有class為story的標簽

? ??????????????????????????soup.select("p.sister")這個方法可以找到所有class為story的p標簽

3.也可以通過id去查找

? ? ? ? ? ? ? ? 例如:

? ??????????????????????????soup.select("#link1")這個方法可以找到所有id = #link的標簽

? ??????????????????????????soup.select("a#link2")而這個方法可以得到所有id = #link的a標簽

4.也可以通過屬性來查找

? ? ? ? ? ? ? ? ? ? ? ? ? ? 一、是否存在某種屬性:

????????????????????????????????????????soup.select('a[href]')尋找存在href屬性的標簽

? ? ? ? ? ? ? ? ? ? ? ? ? ? 二、通過屬性的值去尋找:

? ??????????????????????????????????????soup.select('a[)這條指令可以找到所有href值為http://example.com/elsie的a標簽

5.也可以通過語言來設置:

????????????????????????????看這個例子:

language = """

<p lang = "en">Hello</p>

<p lang = "en-us">Howdy,y'all</p>

<p lang="en-gb">Pip-pip, old fruit</p>

<p lang="fr">Bonjour mes amis</p>

"""

soup = BeautifulSoup(language,'lxml')

soup.select('p[lang|=en]')這條指令可以得到一下結果:[<p lang= "en">Hello</p>,<p lang="en-us">Howdy,y'all</p>,<p lang="en-gb">Pip-pip, old fruit</p>]

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容