網頁中有用的信息通常存在於網頁中的文本或各種不同標簽的屬性值,為了獲得這些網頁信息,有必要有一些查找方法可以獲取這些文本值或標簽屬性。而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>
- </body>
- </html>
以上代碼是一個生態金字塔的簡單展示,為了找到其中的第一生產者,第一消費者或第二消費者,我們可以使用Beautiful Soup的查找方法。一般來說,為了找到BeautifulSoup對象內任何第一個標簽入口,我們可以使用find()方法。
找到第一生產者
可以明顯看到,生產者在第一個<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)
輸出得到:plants
find()說明
find()函數如下:
find(name,attrs,recursive,text,**wargs)
這些參數相當於過濾器一樣可以進行篩選處理。
不同的參數過濾可以應用到以下情況:
- 查找標簽,基於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
基於定制屬性的查找
- customattr = ""'<p data-custom="custom">custom attribute
- example</p>"""
- customsoup = BeautifulSoup(customattr,'lxml')
- customSoup.find(data-custom="custom")
那么則會報錯。原因是在Python中變量不能呢含有-這個字符,而我們傳遞的data-custom有-這個字符。
- css_class = soup.find(attrs={'class':'primaryconsumerlist'})
- print(css_class)
還有另一個辦法。BeautifulSoup有一個特別的關鍵字參數class_。示例:
- css_class = soup.find(class_ = "primaryconsumers" )
方法2:
- 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
把方法進行組合后進行查找
使用find_all查找
查找所有三級消費者
- all_tertiaryconsumers =
- soup.find_all(class_="tertiaryconsumerslist")
其all_tertiaryconsumers的類型是列表。
- for tertiaryconsumer in all_tertiaryconsumers:
- print(tertiaryconsumer.div.string)
輸出:
理解用於find_all()的參數
- email_ids = soup.find_all(text=emailid_regexp)
- print(email_ids)
輸出:[u'abc@example.com',u'xyz@example.com',u'foo@example.com']
- email_ids_limited = soup.find_all(text=emailid_regexp,limit=2)
- print(email_ids_limited)
- all_texts = soup.find_all(text=True)
- print(all_texts)
輸出:
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']
- 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,那么超找只會找到該對象的最近后代。
通過標簽之間的關系進行查找
查找父標簽
- primaryconsumers = soup.find_all(class_="primaryconsumerlist")
- primaryconsumer = primaryconsumers[0]
- parent_ul = primaryconsumer.find_parents('ul')
- print(parent_ul)
一個簡單的找到一個標簽的父標簽的方法就是使用find_parent()卻不帶任何參數。


- producers= soup.find(id='producers')
- next_siblings = producers.find_next_siblings()
- print(next_siblings)
查找下一個
- first_div = soup.div
- all_li_tags = first_div.find_all_next("li")
輸出“:
<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>]