python網絡爬蟲(一)

Python是一門高級的動態的語言,利用它進行網絡數據的抓取是非常方便的。代碼的實現非常的精簡。

在本次python爬蟲中,我們將使用到以下python第三方庫:

1.requests(urllib3) 用於發起http請求,相對於python自帶的urllib2模塊,更加的pythonic
2.redis-py 連接redis數據庫,用於保存待抓取的url隊列,並實現分佈式
3.gevent 實現併發抓取,相對於python的threading性能更好,但是有monkey-patch
4.pybloom 布隆過濾器,實現url的去重功能
5.MySQL-python 存儲網頁以及提取到的結構化數據
6.Chardet 檢測網頁編碼
7.Parsel 基於lxml實現的網頁解析器,用法更簡單,scrapy用的就是這個,速度可以媲美lxml
8.Selenium + phantomjs 抓取js網頁

以上這些就是目前在爬蟲實現中會用到的python庫,這對於目前的我來說,是最優的解決方法。當然,如果有更好的方法可以代替上面列出的一些第三方庫,我也會及時更新。

言歸正傳,開始我們的網頁抓取旅途吧!

首先,我們探討一下,我們從客戶端發起一個http請求到接受到一個response中間經歷了哪些過程?
1.我們需要一個用於請求的url
2.dns解析,將我們請求url中的host提取出來,並進行相應的dns解析,解析成ip地址,其中http請求的端口號默認是80, https請求的默認端口號是443
3.根據解析出來的ip地址跟端口號以及host,進行tcp/ip連接,綁定到特定的主機上
4.發送http請求,優先發送headers,如果擁有body部分,再發送body部分
5.接受http響應
以上步驟中我們忽略代理這個中間件

通過以上五個步驟,我們就可以開始構建我們的第一個請求了。
Requests庫的用法非常的簡單,簡單的兩句就可以抓取一個網頁:

url = 'http://www.example.com'
r = requests.get(url)

Dns解析,tcp/ip鏈接,發送http請求我們完全不需要去考慮,requests已經幫我們都實現了。有興趣的同學,可以參考python內置模塊httplib

只要成功請求,就會返回一個response對象,否則就會拋出一個異常,requests的所有異常都繼承自requests.exceptions.RequestException.類。

我們可以通過r.status_code來查看網頁的返回碼,正常網頁的返回碼是200,如果返回的是一個已經不存在的網頁,狀態碼就是400+, 如果是服務器錯誤,就是500+。默認情況下是不會返回300+的狀態碼的,因爲requests會自動爲我們重定向。如果要禁用重定向,傳入allow_redirects=False關鍵詞參數即可。在我們的爬蟲進行網絡數據抓取的時候,建議大家最好禁用重定向,因爲重定向會非常的耗時,比如存在dns解析,tcp/ip鏈接,然後再發起http請求,之後等待響應。

在http請求的時候,requests會給我們帶上一個headers,裏面有一些默認的參數值。可以通過response.request.headers進行查看,下面我們以請求百度首頁爲例,看看headers會默認帶上哪些參數。
{‘accept-encoding’: ‘gzip, deflate’, ‘accept’: ‘/’, ‘user-agent’: ‘python-requests/版本號’ }
這是requests默認給我們帶上的參數。

’accept-encoding’向服務器表明了我們客戶端可以接受的數據編碼類型,只要服務器探測到客戶端的請求的頭部中有這個字段,那麼就會發送相應的編碼的數據過去。默認情況下我們接受到的response都是經過gzip壓縮過的,因爲目前來說gzip壓縮的比率是最好的,這樣可以減少數據的傳輸,提高性能,減少延遲。

‘accept’向服務器表明了我們客戶端可以接受哪種數據類型,/表示我們可以接受任何類型。但事實上並不是這樣,大部分時候我們只需要接受html文本即可。

‘User-agent’ 相信大部分寫過爬蟲的都對這個不會陌生,user-agent用來向服務器表明客戶端的身份。有一些反爬蟲較爲嚴格的服務器會根據user-agent來決定是夠返回響應數據,大部分時候,我們的做法是去獲取一大批瀏覽器的user-agent,這種做法可以給我們提供不少的幫助。

如果返回響應的是文本內容,使用r.text即可,二進制數據則使用r.content。

前面我們使用了requests.get(url)這種方法來請求url,在實際使用中你就會發現,這很容易被禁止掉。所以我們需要做一些設置。

headers = {'user-agent': 'xxxx',
       'host': 'xxx',
       'accept': 'xxx',
       'accept-charset': 'xxx',
       'accept-language': 'xxx',
           'referer': 'xxxx',}  

1.user-agent用戶代理,百度谷歌一下隨便找
2.host請求url的host, 可使用urlparse模塊
3.accept如果只能接受html,就寫成text/html,具體參考可去w3school上去看詳細內容,也可以看看《http權威指南》
4.accept-charset建議統一爲utf-8,python裏面的字符編碼問題誰用誰知道
5.accept-language如果請求中文頁面就統一爲zh-cn
6.referer:請求url的來源頁面,舉個列子,我們在瀏覽器在通過連接點擊下一個頁面,就會有referer頭部,這對服務器來說是友好的。當然還有一些條件請求頭部,比如if-modified-since等,這留到以後講解。
上面的這些headers實在不瞭解的話,推薦可以看看《http權威指南》

最後加上requests中的一些參數,我們最後的請求如下:

import requests

headers = {'user-agent': "Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/50.0.2657.3+Safari/537.36",
       'host': url_host,
       'accept': 'text/html',
       'accept-charset': 'utf-8',
       'accept-language': 'zh-cn',
       'referer': referer_url,}
#如果想要再加上一些其他的請求頭部或者完善請求頭部,推薦書籍《http權威指南》

requests.get(url=url, 
         headers=headers,
         timeout=5, 
         allow_redirects=False)

當然requests和urllib3中還有其他非常多的功能,比如連接池,會話鏈接,安全認證,更換代理,cookie處理等等,這都是我們在寫爬蟲的時候會用到的,具體參考官方指南

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章