複雜的HTML解析 003

當咱們想要從複雜的網絡信息中抽取出咱們須要的信息時,不假思索的寫出層層抽取的代碼是很是不理智的。這樣的代碼又臭又長,難以閱讀,且容易失效。正確的方法是三思然後行,使用正確的技巧方法寫出簡潔,易懂,擴展性強的代碼。 重要的事情說三遍:三思然後行,三思然後行,三思然後行html

1.class和id抽取

網頁的class屬性和id屬性是很是豐富的,咱們可使用這些屬性來抽取信息: 例子:python

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://pythonscraping.com/pages/warandpeace.html")
#網頁html代碼賦給變量bs0bj
bs0bj = BeautifulSoup(html)
#返回一個含有class=green屬性的列表
namelist = bs0bj.findAll("span",{"class":"green"})
#遍歷輸出列表中不含標籤的文字。
for name in namelist:
	print(name.get_text())

.get_text():把正在處理的html文檔中的全部標籤都清除,返回一個只包含文字的字符串,通常狀況下因儘量保留標籤,在最後狀況下使用get_text()。正則表達式

2.find()和finaall()

find()和finaall()這兩個函數是很是經常使用的,咱們能夠用它們找到須要的標籤或標籤組。 函數的格式定義以下:api

findAll(tag, attributes, recursive, text, limit, keywords)

find(tag, attributes, recursive, text, keywords)
  • tag:能夠傳入一個標籤或多個標籤的標籤組,.findAll({"h1","h2","h3","h4","h5","h6"})
  • attributes:用一個字典封裝的一個標籤的若干屬性和對應的屬性值
  • recursive:是否遞歸查找子標籤,默認爲true,若是設置爲False,則只查找一級標籤。
  • text:用來匹配標籤的文本內容,不是標籤的屬性,切記。
  • limit:限制數量,當爲1時至關於find()函數,設置爲n時,顯示前n個,按在網頁上的順序排列顯示。
  • keyword:選擇具備指定屬性的標籤。

3.beautifulsoup對象

  • BeautifulSoup 對象:前面代碼中的bsObj
  • Tag 對象 :前面代碼中的bsObj.div.h1
  • NavigableString 對象:標籤裏的文字
  • comment 對象:查找html的註釋標籤, <!--like this one-->

4.導航樹:

整個html頁面能夠簡化爲一棵樹,以下所示:網絡

輸入圖片說明

輸入圖片說明

1.處理子標籤和後代標籤:函數

通常狀況下,beautifulsoup老是處理當前標籤下的後代標籤,如bs0bj.body.h1是處理當前body標籤下的第一個h1標籤。bs0bj.body.finaAll("img")是找到第一div標籤下的索引img列表。學習

若是隻想要找到子標籤,可使用.children標籤。測試

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for child in bsObj.find("table",{"id":"giftList"}).children:
    print(child)

上面的代碼會打印giftlist表格中的索引產品的數據行。this

使用descendants()標籤能夠輸出全部的後代標籤。url

2.兄弟標籤: 使用next_siblings()函數能夠處理兄弟標籤。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for sibling in bsObj.find("table",{"id":"giftList"}).tr.next_siblings:
print(sibling)

使用兄弟標籤會跳過標籤自身,由於自身不能看成本身的兄弟,同時兄弟標籤只能查找後面的標籤,不能查找自身以及前面的兄弟標籤。

與next_siblings()相似,previous_siblings()函數是查找前面的兄弟節點。

同時還有next_siblings()和previous_siblings()函數,它們的做業是返回單個標籤。

3.父標籤

使用parent和parents標籤能夠查找給定標籤的父標籤或父標籤列表。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
print(bsObj.find("img",{"src":"../img/gifts/img1.jpg" 
}).parent.previous_sibling.get_text())

上面代碼的意思是找到給定標籤的父標籤的前一個兄弟標籤中的文字。

5.正則表達式:

正則表達式是很是豐富的,可是上手很簡單。能夠本身搜索一些教程學習。 正則測試:http://www.regexpal.com/

6.正則表達式與BeautifulSoup

正則表達式是很是有用的,舉個例子,加入你想要抓取索引的img圖片,使用finaall()獲得的結果可能會出乎意料,多了許多隱藏的圖片或不相關的圖片,此時可使用正則表達式。咱們發現想要獲取的圖片源代碼格式以下:

<img src="../img/gifts/img3.jpg">

這樣咱們能夠直接經過文件路徑來查找信息,

from urllib.request
import urlopenfrom bs4
import BeautifulSoupimport re

html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
images = bsObj.findAll("img", {"src":re.compile("\.\.\/img\/gifts/img.*\.jpg")})
for image in images:
    print(image["src"])

上面的例子使用了正則表達式匹配了以../img/gifts/img開頭,以.jpg結尾的圖片。結果以下:

../img/gifts/img1.jpg
../img/gifts/img2.jpg
../img/gifts/img3.jpg
../img/gifts/img4.jpg
../img/gifts/img6.jpg

6.標籤屬性:

對於一個標籤對象,可使用下面代碼得到它的所有屬性:

myTag.attrs

得到的屬性存在一個字典中,能夠取出某一個屬性

myTag.attrs["href"]

7.lambda表達式

相關文章
相關標籤/搜索