使用python抓取網頁(以人人網新鮮事和團購網資訊為例)
from http://www.pinkyway.info/2010/12/19/fetch-webpage-by-python/?replytocom=448
by 穎風斯特
BeautifulSoup, Python, urllib, 人人網, 團購 12 Comments
前一段時間寫的小東西,一直沒工夫把他系統寫出來,今天眼睛疼,就寫寫吧~~(原來博主不蛋疼時也會更新部落格的哈~)
python抓取網頁基礎
python自己帶有很多網路應用相關的模組,如:ftplib用於FTP相關操作,smtplib和poplib用於收發電子郵件等等,利用這些
模組自己寫一個FTP軟體或是郵件用戶端類軟體完全是可能的,我就簡單的試過完全用python指令碼收發郵件和操作自己的FTP伺服器。當然,這都不是今
天的主角,我們今天要用到的幾個模組是:urllib,urllib2,cookielib,BeautifulSoup,我們先來簡單介紹下。
urllib和urllib2自然都是處理URL相關的操作,urllib可以從指定的URL下載檔案,或是對一些字串進行編碼解碼以使他們成為特定的
URL串,而urllib2則比urllib更2一點,哦不對,是更牛逼一點。它有各種各樣的Handler啊,Processor啊可以處理更複雜的問
題,比如網路認證,使用Proxy 伺服器,使用cookie等等。第三個cookielib,顧名思義,專門處理cookie相關的操作,其他的我也沒深入過。
而最後一個包,BeautifulSoup,“美麗的湯”,它是一個第三方的包,專門用於解析HTML和XML檔案,使用非常之傻瓜,我們就要靠它來解析
網頁原始碼了,可以從這裡下載,當然你也可以用easy_install安裝它,這裡還有它的中文使用文檔,有多例子是相當不錯的。
我們先來看看最簡單的網頁抓取,其實網頁抓取就是將所要的網頁原始碼檔案下載下來,然後對其分析以提取對自己有用的資訊。最簡單的抓取用一句話就可以搞定:
12 |
import urllib html_src = urllib.urlopen( 'http://www.baidu.com' ).read() |
這樣就會列印出百度首頁的HTML源碼了,還是很easy的。urllib的urlopen函數會返回一個“類檔案”對象,所以直接調用
read()即可擷取裡面的內容了。但是這樣列印得到的內容是一團糟,排版不好看,編碼問題也沒解決,所以是看不到中文字元的。這就需要我們的
BeautifulSoup包了,我們可以使用上面得到的原始碼字串html_src來初始化一個BeautifulSoup對象:
12 |
from BeautifulSoup import BeautifulSoup parser = BeautifulSoup(html_src) |
這樣,後續處理HTML源碼的工作交給parser變數來負責就好,我們可以簡單的調用parser的prettify函數來相對美觀的顯示源碼,
可以看到這樣就能看到中文字元了,因為BeautifulSoup能自動處理字元問題,並將返回結果都轉化為Unicode編碼格式。另
外,BeautifulSoup還能迅速定位到滿足條件的指定標籤,後面我們會用到~
抓取人人網的新鮮事
前面講的是最簡單的抓取情形了,但通常我們需要面對更複雜的情形,拿人人網來說,需要登入自己的帳號才能顯示新鮮事,這樣我們就只能求助於更2一點
的urllib2模組了。試想,我們需要一個opener來開啟你的人人網首頁,而為了進入首先就需要認證,而這個登入認證需要cookie的支援,那我
們就需要在這個opener之上搭建一個處理cookie的Handler:
1234 |
import urllib,urllib2,cookielib from BeautifulSoup import BeautifulSoup myCookie = urllib2.HTTPCookieProcessor(cookielib.CookieJar()); opener = urllib2.build_opener(myCookie) |
首先import我們需要的所有模組,然後使用urllib2模組的HTTPCookieProcessor搭建一個處理cookie的
Handler,傳入cookielib模組的CookieJar函數作為參數,這個這個函數處理HTTP的cookie,簡單地說,它從HTTP請求中
提取cookie,然後將其返回給HTTP響應。然後利用urllib2的build_opener來建立我們需要的opener,這個opener已經
滿足我們處理cookie的要求了。
那麼這個Handler怎麼工作呢,前面說了,它需要捕捉到HTTP請求才行,也就是說,我們需要知道,登入人人的時候發了什麼資料包出去,牛逼的
人可以使用各種命令列抓包工具如Tcpdump一類的,我等小民還是圖形化的吧。這裡我們藉助於Firefox的HttpFox來實現,可以從這裡添 加這個牛逼的外掛程式。安裝好該外掛程式以後,我們用Firefox登入人人網,然後輸入自己的帳號和密碼,然後,別急,不要按登入按鈕,從狀態列開啟
HttpFox外掛程式,點擊Start按鈕開始抓包,然後點擊人人網的登陸,登陸過程完成後點擊HttpFox的Stop停止抓包,如果一切正常的話應該可
以看到如下資訊了。
我們可以看到登陸人人的過程中瀏覽器向人人的伺服器發送POST請求資料,有四項,其中兩項是你的帳號和密碼。下面我們就利用代碼類比發出同樣的請求就可以啦。
123456789 |
post_data = { 'email' : 'xxxxx' , 'password' : 'xxxxx' , 'origURL' : 'http://www.renren.com/Home.do' , 'domain' : 'renren.com' } req = urllib2.Request( 'http://www.renren.com/PLogin.do' , urllib.urlencode(post_data)) html_src = openner. open (req).read() parser = BeautifulSoup(html_src) |
首先,構造一個字典來儲存我們剛才抓到的POST資料,然後通過urllib2的Request類來自己構造一個“請求”對象,請求的遞交網址就是
上面捕捉的POST請求的URL部分,後面跟著我們的POST資料,注意,這裡需要使用urllib的urlencode方法重新編碼,以使其成為合法的
URL串。下面的過程就跟前面提到的簡單抓取過程一樣,只不過這裡開啟的不是簡單的網址,而是將網址和POST資料封裝後的Request請求,同樣,我
們將源碼賦給BeautifulSoup以便後面處理。
現在我們的parser裡儲存的就是含有好友新鮮事的網頁源碼了,我們怎樣提取有用的資訊呢?分析網頁這種粗活還是交給Firefox的FireBug(這裡下載)來玩吧。登入你的人人網,隨意右擊一下新鮮事裡某個人的狀態,選擇“查看元素”,就會蹦出如下視窗,顯示出你所點擊的部分對應的源碼:
我們可以看到,每個新鮮事對應著article標籤,我們再仔細看看article標籤的詳細內容:
裡面的h3標籤包含了好友的姓名和狀態,當然,還有一些肥豬流的表情地址,接觸過HTML的對這個應該不陌生吧。所以我們要抓的就是這個h3啦!
BeautifulSoup抓取標籤內容
下面就是我們的parser露臉的時候了,BeautifulSoup提供了很多定位標籤的方法,簡單的說,主要就是find函數和findAll
函數了,常用的參數就是name和attrs,一個是標籤的名字,一個是標籤的屬性,name是個字串,而attrs是個字典,比如說
find(‘img’,{‘src’:’abc.jpg’})就會返回類似這樣的標籤:<img
src=”abc.jpg”>。而find與findAll的區別就是,find只返回第一個滿足要求的標籤,而findAll返回所有符合要求的
標籤的列表。擷取標籤後,還有很多方便的方法擷取子標籤,例如,通過點操作符,tag.a可以擷取tag所代表的標籤下的子標籤a,再如
tag.contents可以擷取其所有孩子的列表,更多應用可以查看它的文檔。下面就具體到本例來看怎麼抓取我們想要的內容。
1234567891011 |
article_list = parser.find( 'div' , 'feed-list' ).findAll( 'article' ) for my_article in article_list: state = [] for my_tag in my_article.h3.contents: factor = my_tag.string if factor ! = None : factor = factor.replace(u '/xa0' ,'') factor = factor.strip(u '/r/n' ) factor = factor.strip(u '/n' ) state.append(factor) print ' ' .join(state) |
這裡,我們通過find(‘div’,’feed-list’).findAll(‘article’)擷取class屬性為‘feed-
list’的div標籤,第二個參數直接為一個字串時代表的就是CSS的class屬性了,然後擷取其所有article的列表,對照上面的圖,這句其
實就是獲得了所有新鮮事的列表。然後我們遍曆這個列表,對於每個article標籤再擷取其h3標籤,並提取內容,如果標籤中直接含有文本,則可以通過
string屬性獲得,最後,我們去掉一些控制字元,如換行一類的。最終將結果列印出來,當然這隻能擷取一小部分,“更多新鮮事”的功能還不能達到,有興
趣的繼續研究吧,我覺得通過HttpFox是不難實現的吧。
團購資訊彙總小工具
用同樣的知識,我們還可以做一些有趣的應用,像現在很火的團購資訊彙總,其實思路還是很容易的,就是分析網站的原始碼,提取團購的標題,圖片和價格
就好了。這裡放出源碼檔案,有興趣的可以研究下!用PyQt做的介面,按鈕的功能還沒有實現,只能提取“美團”,“糯米網”,“QQ團購”三個網站,從下
拉列表框裡選擇就可顯示,圖片會儲存在本地目錄裡,來個看看吧~
打叉的按鈕功能沒有實現哦~這裡是檔案下載,一個pyw主表單檔案,兩外兩個py檔案一個是UI,一個是Resource。