Python網(wǎng)頁(yè)解析利器BeautifulSoup安裝使用介紹
python解析網(wǎng)頁(yè),無(wú)出BeautifulSoup左右,此是序言
安裝
BeautifulSoup4以后的安裝需要用eazy_install,如果不需要最新的功能,安裝版本3就夠了,千萬(wàn)別以為老版本就怎么怎么不好,想當(dāng)初也是千萬(wàn)人在用的啊。安裝很簡(jiǎn)單
然后把里面的BeautifulSoup.py這個(gè)文件放到你python安裝目錄下的site-packages目錄下
site-packages是存放Python第三方包的地方,至于這個(gè)目錄在什么地方呢,每個(gè)系統(tǒng)不一樣,可以用下面的方式找一下,基本上都能找到
$ sudo find / -name "site-packages" -maxdepth 5 -type d
$ find ~ -name "site-packages" -maxdepth 5
當(dāng)然如果沒(méi)有root權(quán)限就查找當(dāng)前用戶(hù)的根目錄
$ find ~ -name "site-packages" -maxdepth 5 -type d
如果你用的是Mac,哈哈,你有福了,我可以直接告訴你,Mac的這個(gè)目錄在/Library/Python/下,這個(gè)下面可能會(huì)有多個(gè)版本的目錄,沒(méi)關(guān)系,放在最新的一個(gè)版本下的site-packages就行了。使用之前先import一下
from BeautifulSoup import BeautifulSoup
使用
在使用之前我們先來(lái)看一個(gè)實(shí)例
現(xiàn)在給你這樣一個(gè)頁(yè)面
它是豆瓣電影分類(lèi)下的喜劇電影,如果讓你找出里面評(píng)分最高的100部,該怎么做呢
好了,我先曬一下我做的,鑒于本人在CSS方面處于小白階段以及天生沒(méi)有美術(shù)細(xì)菌,界面做的也就將就能看下,別吐
接下來(lái)我們開(kāi)始學(xué)習(xí)BeautifulSoup的一些基本方法,做出上面那個(gè)頁(yè)面就易如反掌了
鑒于豆瓣那個(gè)頁(yè)面比較復(fù)雜,我們先以一個(gè)簡(jiǎn)單樣例來(lái)舉例,假設(shè)我們處理如下的網(wǎng)頁(yè)代碼
<html>
<head><title>Page title</title></head>
<body>
<p id="firstpara" align="center">
This is paragraph
<b>
one
</b>
.
</p>
<p id="secondpara" align="blah">
This is paragraph
<b>
two
</b>
.
</p>
</body>
</html>
你沒(méi)看錯(cuò),這就是官方文檔里的一個(gè)樣例,如果你有耐心,看官方文檔就足夠了,后面的你都不用看
http://www.leeon.me/upload/other/beautifulsoup-documentation-zh.html
初始化
首先將上面的HTML代碼賦給一個(gè)變量html如下,為了方便大家復(fù)制這里貼的是不帶回車(chē)的,上面帶回車(chē)的代碼可以讓大家看清楚HTML結(jié)構(gòu)
html = '<html><head><title>Page title</title></head><body><p id="firstpara" align="center">This is paragraph<b>one</b>.</p><p id="secondpara" align="blah">This is paragraph<b>two</b>.</p></body></html>'
初始化如下:
soup = BeautifulSoup(html)
我們知道HTML代碼可以看成一棵樹(shù),這個(gè)操作等于是把HTML代碼解析成一種樹(shù)型的數(shù)據(jù)結(jié)構(gòu)并存儲(chǔ)在soup中,注意這個(gè)數(shù)據(jù)結(jié)構(gòu)的根節(jié)點(diǎn)不是<html>,而是soup,其中html標(biāo)簽是soup的唯一子節(jié)點(diǎn),不信你試試下面的操作
print soup
print soup.contents[0]
print soup.contents[1]
前兩個(gè)輸出結(jié)果是一致的,就是整個(gè)html文檔,第三條輸出報(bào)錯(cuò)IndexError: list index out of range
查找節(jié)點(diǎn)
查找節(jié)點(diǎn)有兩種反回形式,一種是返回單個(gè)節(jié)點(diǎn),一種是返回節(jié)點(diǎn)list,對(duì)應(yīng)的查找函數(shù)分別為find和findAll
單個(gè)節(jié)點(diǎn)
1.根據(jù)節(jié)點(diǎn)名
## 查找head節(jié)點(diǎn)
print soup.find('head') ## 輸出為<head><title>Page title</title></head>
## or
## head = soup.head
這種方式查找到的是待查找節(jié)點(diǎn)最近的節(jié)點(diǎn),比如這里待查找節(jié)點(diǎn)是soup,這里找到的是離soup最近的一個(gè)head(如果有多個(gè)的話(huà))
2.根據(jù)屬性
## 查找id屬性為firstpara的節(jié)點(diǎn)
print soup.find(attrs={'id':'firstpara'})
## 輸出為<p id="firstpara" align="center">This is paragraph<b>one</b>.</p>
## 也可節(jié)點(diǎn)名和屬性進(jìn)行組合
print soup.find('p', attrs={'id':'firstpara'}) ## 輸出同上
3.根據(jù)節(jié)點(diǎn)關(guān)系
節(jié)點(diǎn)關(guān)系無(wú)非就是兄弟節(jié)點(diǎn),父子節(jié)點(diǎn)這樣的
p1 = soup.find(attrs={'id':'firstpara'}) ## 得到第一個(gè)p節(jié)點(diǎn)
print p1.nextSibling ## 下一個(gè)兄弟節(jié)點(diǎn)
## 輸出<p id="secondpara" align="blah">This is paragraph<b>two</b>.</p>
p2 = soup.find(attrs={'id':'secondpara'}) ## 得到第二個(gè)p節(jié)點(diǎn)
print p2.previousSibling ## 上一個(gè)兄弟節(jié)點(diǎn)
## 輸出<p id="firstpara" align="center">This is paragraph<b>one</b>.</p>
print p2.parent ## 父節(jié)點(diǎn),輸出太長(zhǎng)這里省略部分 <body>...</body>
print p2.contents[0] ## 第一個(gè)子節(jié)點(diǎn),輸出u'This is paragraph'
多個(gè)節(jié)點(diǎn)
將上面介紹的find改為findAll即可返回查找到的節(jié)點(diǎn)列表,所需參數(shù)都是一致的
1.根據(jù)節(jié)點(diǎn)名
## 查找所有p節(jié)點(diǎn)
soup.findAll('p')
2.根據(jù)屬性查找
## 查找id=firstpara的所有節(jié)點(diǎn)
soup.findAll(attrs={'id':'firstpara'})
需要注意的是,雖然在這個(gè)例子中只找到一個(gè)節(jié)點(diǎn),但返回的仍是一個(gè)列表對(duì)象
上面的這些基本查找功能已經(jīng)可以應(yīng)付大多數(shù)情況,如果需要各個(gè)高級(jí)的查找,比如正則式,可以去看官方文檔
獲取文本
getText方法可以獲取節(jié)點(diǎn)下的所有文本,其中可以傳遞一個(gè)字符參數(shù),用來(lái)分割每個(gè)各節(jié)點(diǎn)之間的文本
## 獲取head節(jié)點(diǎn)下的文本
soup.head.getText() ## u'Page title'
## or
soup.head.text
## 獲取body下的所有文本并以\n分割
soup.body.getText('\n') ## u'This is paragraph\none\n.\nThis is paragraph\ntwo\n.'
實(shí)戰(zhàn)
有了這些功能,文章開(kāi)頭給出的那個(gè)Demo就好做了,我們?cè)賮?lái)回顧下豆瓣的這個(gè)頁(yè)面
http://movie.douban.com/tag/%E5%96%9C%E5%89%A7
如果要得到評(píng)分前100的所有電影,對(duì)這個(gè)頁(yè)面需要提取兩個(gè)信息:1、翻頁(yè)鏈接;2、每部電影的信息(外鏈,圖片,評(píng)分、簡(jiǎn)介、標(biāo)題等)
當(dāng)我們提取到所有電影的信息后再按評(píng)分進(jìn)行排序,選出最高的即可,這里貼出翻頁(yè)提取和電影信息提取的代碼
## filename: Grab.py
from BeautifulSoup import BeautifulSoup, Tag
import urllib2
import re
from Log import LOG
def LOG(*argv):
sys.stderr.write(*argv)
sys.stderr.write('\n')
class Grab():
url = ''
soup = None
def GetPage(self, url):
if url.find('http://',0,7) != 0:
url = 'http://' + url
self.url = url
LOG('input url is: %s' % self.url)
req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"})
try:
page = urllib2.urlopen(req)
except:
return
return page.read()
def ExtractInfo(self,buf):
if not self.soup:
try:
self.soup = BeautifulSoup(buf)
except:
LOG('soup failed in ExtractInfo :%s' % self.url)
return
try:
items = self.soup.findAll(attrs={'class':'item'})
except:
LOG('failed on find items:%s' % self.url)
return
links = []
objs = []
titles = []
scores = []
comments = []
intros = []
for item in items:
try:
pic = item.find(attrs={'class':'nbg'})
link = pic['href']
obj = pic.img['src']
info = item.find(attrs={'class':'pl2'})
title = re.sub('[ \t]+',' ',info.a.getText().replace(' ','').replace('\n',''))
star = info.find(attrs={'class':'star clearfix'})
score = star.find(attrs={'class':'rating_nums'}).getText().replace(' ','')
comment = star.find(attrs={'class':'pl'}).getText().replace(' ','')
intro = info.find(attrs={'class':'pl'}).getText().replace(' ','')
except Exception,e:
LOG('process error in ExtractInfo: %s' % self.url)
continue
links.append(link)
objs.append(obj)
titles.append(title)
scores.append(score)
comments.append(comment)
intros.append(intro)
return(links, objs, titles, scores, comments, intros)
def ExtractPageTurning(self,buf):
links = set([])
if not self.soup:
try:
self.soup = BeautifulSoup(buf)
except:
LOG('soup failed in ExtractPageTurning:%s' % self.url)
return
try:
pageturning = self.soup.find(attrs={'class':'paginator'})
a_nodes = pageturning.findAll('a')
for a_node in a_nodes:
href = a_node['href']
if href.find('http://',0,7) == -1:
href = self.url.split('?')[0] + href
links.add(href)
except:
LOG('get pageturning failed in ExtractPageTurning:%s' % self.url)
return links
def Destroy(self):
del self.soup
self.soup = None
接著我們?cè)賮?lái)寫(xiě)個(gè)測(cè)試樣例
## filename: test.py
#encoding: utf-8
from Grab import Grab
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
grab = Grab()
buf = grab.GetPage('http://movie.douban.com/tag/喜劇?start=160&type=T')
if not buf:
print 'GetPage failed!'
sys.exit()
links, objs, titles, scores, comments, intros = grab.ExtractInfo(buf)
for link, obj, title, score, comment, intro in zip(links, objs, titles, scores, comments, intros):
print link+'\t'+obj+'\t'+title+'\t'+score+'\t'+comment+'\t'+intro
pageturning = grab.ExtractPageTurning(buf)
for link in pageturning:
print link
grab.Destroy()
OK,完成這一步接下來(lái)的事兒就自個(gè)看著辦吧
本文只是介紹了BeautifulSoup的皮毛而已,目的是為了讓大家快速學(xué)會(huì)一些基本要領(lǐng),想當(dāng)初我要用什么功能都是去BeautifulSoup的源代碼里一個(gè)函數(shù)一個(gè)函數(shù)看然后才會(huì)的,一把辛酸淚啊,所以希望后來(lái)者能夠通過(guò)更便捷的方式去掌握一些基本功能,也不枉我一字一句敲出這篇文章,尤其是這些代碼的排版,真是傷透了腦筋
- python3第三方爬蟲(chóng)庫(kù)BeautifulSoup4安裝教程
- Python爬蟲(chóng)包BeautifulSoup簡(jiǎn)介與安裝(一)
- python爬蟲(chóng)開(kāi)發(fā)之Beautiful Soup模塊從安裝到詳細(xì)使用方法與實(shí)例
- Windows8下安裝Python的BeautifulSoup
- python beautiful soup庫(kù)入門(mén)安裝教程
- python3解析庫(kù)BeautifulSoup4的安裝配置與基本用法
- python BeautifulSoup庫(kù)的安裝與使用
- python解析庫(kù)Beautiful?Soup安裝的詳細(xì)步驟
相關(guān)文章
用Python中的__slots__緩存資源以節(jié)省內(nèi)存開(kāi)銷(xiāo)的方法
這篇文章主要介紹了用Python中的__slots__通過(guò)緩存資源的方式以節(jié)省內(nèi)存開(kāi)銷(xiāo)的方法,且示例代碼非常簡(jiǎn)單,需要的朋友可以參考下2015-04-04python實(shí)現(xiàn)微信小程序自動(dòng)回復(fù)
這篇文章主要介紹了python實(shí)現(xiàn)微信小程序自動(dòng)回復(fù),使用itchat模塊進(jìn)行微信私聊消息以及群消息自動(dòng)回復(fù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09Python實(shí)現(xiàn)定時(shí)任務(wù)的九種方案總結(jié)
定時(shí)任務(wù)是編程中常見(jiàn)的需求,它可以按照預(yù)定的時(shí)間表執(zhí)行特定的任務(wù)或操作,在Python中,有多種方法可以實(shí)現(xiàn)定時(shí)任務(wù),下面小編就來(lái)和大家詳細(xì)講講吧2023-11-11使用python將最新的測(cè)試報(bào)告以附件的形式發(fā)到指定郵箱
這篇文章主要介紹了使用python將最新的測(cè)試報(bào)告以附件的形式發(fā)到指定郵箱,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09讓Python腳本暫停執(zhí)行的幾種方法(小結(jié))
這篇文章主要介紹了讓Python腳本暫停執(zhí)行的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python BeautifulSoup設(shè)置頁(yè)面編碼的方法
這篇文章主要介紹了python BeautifulSoup設(shè)置頁(yè)頁(yè)編碼的方法,本文直接給出代碼救命,需要的朋友可以參考下2015-04-04