1. 程式人生 > >Python 之 Beautiful Soup 4文件

Python 之 Beautiful Soup 4文件

*****************簡單版******************

入門

(ps:其實入門什麼的看官方文件是最好的了,這裡只是記錄一下簡單的用法。)

  首先先介紹實際工作中最常用的幾個方法:

  舉例的html程式碼(就用官方例子好了):

複製程式碼
 1 <html>
 2     <head>
 3         <title>Page title</title>
 4     </head>
 5     <body>
 6         <p id="firstpara" align
="center"> 7 This is paragraph<b>one</b>. 8 </p> 9 <p id="secondpara" align="blah"> 10 This is paragraph<b>two</b>. 11 </p> 12 </body> 13 </html>
複製程式碼

0、初始化 

1 soup = BeautifulSoup(html) # html為html原始碼字串,type(html) == str

1、用tag獲取相應程式碼塊的剖析樹: 

  既然要分析html,首先要找到對我們有用的tag塊,beautiful提供了非常便利的方式。

複製程式碼
#當用tag作為搜尋條件時,我們獲取的包含這個tag塊的剖析樹:
#<tag><xxx>ooo</xxx></tag>
#這裡獲取head這個塊
head = soup.find('head')
# or
# head = soup.head
# or
# head = soup.contents[0].contents[0]
複製程式碼

執行後,我們會得到:

1 <head
> 2 <title>Page title</title> 3 </head>

  find方法在當前tag剖析樹(當前這個html程式碼塊中)尋找符合條件的子樹並返回。find方法提供多種查詢方式,包括用喜聞樂見的regex哦~之後會詳細介紹。

  contents屬性是一個列表,裡面儲存了該剖析樹的直接兒子。

如:

1 html = soup.contents[0] # <html> ... </html>
2 head = html.contents[0] # <head> ... </head>
3 body = html.contents[1] # <body> ... </body>

2、用contents[], parent, nextSibling, previousSibling尋找父子兄弟tag

  為了更加方便靈活的分析html程式碼塊,beautifulSoup提供了幾個簡單的方法直接獲取當前tag塊的父子兄弟。

假設我們已經獲得了body這個tag塊,我們想要尋找<html>, <head>, 第一個<p>, 第二個<p>這四個tag塊:

複製程式碼
# body = soup.bodyhtml = body.parent # html是body的父親
head = body.previousSibling # head和body在同一層,是body的前一個兄弟
p1 = body.contents[0] # p1, p2都是body的兒子,我們用contents[0]取得p1 p2 = p1.nextSibling # p2與p1在同一層,是p1的後一個兄弟, 當然body.content[1]也可得到 print p1.text # u'This is paragraphone.' print p2.text # u'This is paragraphtwo.' # 注意:1,每個tag的text包括了它以及它子孫的text。2,所有text已經被自動轉 #為unicode,如果需要,可以自行轉碼encode(xxx)
複製程式碼

   然而,如果我們要尋找祖先或者孫子tag怎麼辦呢?? 用while迴圈嗎? 不, beautifulsoup已經提供了方法。 

3、用find, findParent, findNextSibling, findPreviousSibling尋找祖先或者子孫 tag: 

有了上面的基礎,這裡應該很好理解了,例如find方法(我理解和findChild是一樣的),就是以當前節點為起始,遍歷整個子樹,找到後返回。

  而這些方法的複數形式,會找到所有符合要求的tag,以list的方式放回。他們的對應關係是:find->findall, findParent->findParents, findNextSibling->findNextSiblings...

  如:

1 print soup.findAll('p')
2 # [<p id="firstpara" align="center">This is paragraph <b>one</b>.</p>, <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p>]

  這裡我們重點講一下find的幾種用法,其他的類比:

  find(name=None, attrs={}, recursive=True, text=None, **kwargs)

  1) 搜尋tag:

1 find(tagname)        # 直接搜尋名為tagname的tag 如:find('head')
2 find(list)           # 搜尋在list中的tag,如: find(['head', 'body'])
3 find(dict)           # 搜尋在dict中的tag,如:find({'head':True, 'body':True})
4 find(re.compile('')) # 搜尋符合正則的tag, 如:find(re.compile('^p')) 搜尋以p開頭的tag
5 find(lambda)         # 搜尋函式返回結果為true的tag, 如:find(lambda name: if len(name) == 1) 搜尋長度為1的tag
6 find(True)           # 搜尋所有tag

   2) 搜尋屬性(attrs):

1 find(id='xxx')                                  # 尋找id屬性為xxx的
2 find(attrs={id=re.compile('xxx'), algin='xxx'}) # 尋找id屬性符合正則且algin屬性為xxx的
3 find(attrs={id=True, algin=None})               # 尋找有id屬性但是沒有algin屬性的

  3) 搜尋文字(text):

注意,文字的搜尋會導致其他搜尋給的值如:tag, attrs都失效。

方法與搜尋tag一致

  4) recursive, limit:

  recursive=False表示只搜尋直接兒子,否則搜尋整個子樹,預設為True。

  當使用findAll或者類似返回list的方法時,limit屬性用於限制返回的數量,如findAll('p', limit=2): 返回首先找到的兩個tag 

*4、用next,previous尋找上下文tag(少用) 

  這裡我們主要看看next, next是取得當前的tag的下一個(按程式碼從上到下的順序)tag塊。這與contents是不一樣的,千萬別混淆了哦^ ^

  我們舉個栗子來看看

1 <a>
2     a
3     <b>b</b>
4     <c>c</c>
5 </a>

 我們看看next的實際效果:

1 a = soup.a
2 b = soup.b
3 n1 = b.next
4 n2 = n1.next

 輸出一下:

1 print a.next
2 # u'a'
3 print n1
4 # u'b'
5 print n2
6 # <c>c</c>

所以,next僅僅是獲取文件上的“下一個”的tag,和剖析樹中的位置無關。

當然也有findNext和findAllNext方法。

至於previous, 表示上一個tag塊,就類比一下吧~^ ^

*****************完整版******************

Beautiful Soup 是一個可以從HTML或XML檔案中提取資料的Python庫.它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式.Beautiful Soup會幫你節省數小時甚至數天的工作時間.

這篇文件介紹了BeautifulSoup4中所有主要特性,並切有小例子.讓我來向你展示它適合做什麼,如何工作,怎樣使用,如何達到你想要的效果,和處理異常情況.

文件中出現的例子在Python2.7和Python3.2中的執行結果相同

你可能在尋找 Beautiful Soup3 的文件,Beautiful Soup 3 目前已經停止開發,我們推薦在現在的專案中使用Beautiful Soup 4, 移植到BS4

尋求幫助

如果你有關於BeautifulSoup的問題,可以傳送郵件到 討論組 .如果你的問題包含了一段需要轉換的HTML程式碼,那麼確保你提的問題描述中附帶這段HTML文件的 程式碼診斷 [1]