Python爬蟲學習之(一)| 從零開始
作者:xiaoyu
微信公眾號:Python數據科學
大家好,相信點進來看的小夥伴都對爬蟲非常感興趣,博主也是一樣的。博主剛開始接觸爬蟲的時候,就被深深吸引了,因為感覺SO COOL啊!每當敲完代碼後看著一串串數據在屏幕上浮動,感覺很有成就感,有木有?更厲害的是,爬蟲的技術可以應用到很多生活場景中,例如,自動投票啊,批量下載感興趣的文章、小說、視頻啊,微信機器人啊,爬取重要的數據進行數據分析啊,切實的感覺到這些代碼是給自己寫的,能為自己服務,也能為他人服務,所以人生苦短,我選爬蟲
。
1. 什麼是爬蟲?
首先應該弄明白一件事,就是什麼是爬蟲,為什麼要爬蟲,博主百度了一下,是這樣解釋的:
網路爬蟲(又被稱為網頁蜘蛛,網路機器人,在FOAF社區中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。另外一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。
其實,說白了就是爬蟲可以模擬瀏覽器的行為
做你想做的事,訂製化自己搜索和下載的內容,並實現自動化的操作。比如瀏覽器可以下載小說,但是有時候並不能批量下載,那麼爬蟲的功能就有用武之地了。
實現爬蟲技術的編程環境有很多種,Java
,Python
,C++
等都可以用來爬蟲。但是博主選擇了Python,相信很多人也一樣選擇Python,因為Python確實很適合做爬蟲,豐富的第三方庫十分強大,簡單幾行代碼便可實現你想要的功能,更重要的,Python也是數據挖掘和分析的好能手。這樣爬取數據和分析數據一條龍的服務都用Python真的感覺很棒啊!
2. 爬蟲學習路線
知道了什麼是爬蟲,給大家說說博主總結出的學習爬蟲的基本路線吧,只供大家參考,因為每個人都有適合自己的方法,在這裡只是提供一些思路。
學習Python爬蟲的大致步驟如下:
- 首先學會基本的
Python
語法知識 - 學習Python爬蟲常用到的幾個重要內置庫
urllib
,http
等,用於下載網頁 - 學習正則表達式
re
、BeautifulSoup(bs4
)、Xpath(lxml)
等網頁解析工具 - 開始一些簡單的網站爬取(博主從百度開始的,哈哈),了解爬取數據過程
- 了解爬蟲的一些反爬機制,
header
,robot
,時間間隔
,代理ip
,隱含欄位
等 - 學習一些特殊網站的爬取,解決
登錄
、Cookie
、動態網頁js模擬
等問題 - 學習
selenium
自動化工具,應對非同步載入頁面 - 了解爬蟲與資料庫的結合,如何將爬取數據進行儲存,
Mysql
,Mongodb
- 學習應用Python的
多線程
和非同步
,提高爬蟲效率 - 學習爬蟲的框架,
Scrapy
、PySpider
等 - 學習
redis分散式
爬蟲(數據量龐大的需求) - 學習
增量式
爬蟲
以上便是一個整體的學習概況,好多內容博主也需要繼續學習,關於提到的每個步驟的細節,博主會在後續內容中以實戰的例子逐步與大家分享,當然中間也會穿插一些關於爬蟲的好玩內容。
3. 從第一個爬蟲開始
第一個爬蟲代碼的實現我想應該是從urllib
開始吧,博主開始學習的時候就是使用urllib
庫敲了幾行代碼就實現了簡單的爬數據功能,我想大多夥伴們也都是這麼過來的。當時的感覺就是:哇,好厲害,短短几行竟然就可以搞定一個看似很複雜的任務,於是就在想這短短的幾行代碼到底是怎麼實現的呢,如何進行更高級複雜的爬取呢?帶著這個問題我也就開始了urllib
庫的學習。
首先不得不提一下爬取數據的過程,弄清楚這到底是怎樣一個過程,學習urllib
的時候會更方便理解。
爬蟲的過程
其實,爬蟲的過程和瀏覽器瀏覽網頁的過程是一樣的。道理大家應該都明白,就是當我們在鍵盤上輸入網址點擊搜索之後,通過網路首先會經過DNS伺服器
,分析網址的域名,找到了真正的伺服器。然後我們通過HTTP協議
對伺服器發出GET
或POST
請求,若請求成功,我們就得到了我們想看到的網頁,一般都是用HTML
, CSS
, JS
等前端技術來構建的,若請求不成功,伺服器會返回給我們請求失敗的狀態碼,常見到的503
,403
等。
爬蟲的過程亦是如此,通過對伺服器發出請求得到HTML網頁,然後對下載的網頁進行解析,得到我們想要的內容。當然,這是一個爬蟲過程的一個概況,其中還有很多細節的東西需要我們處理的,這些在後續會繼續與大家分享。
了解了爬蟲的基本過程後,就可以開始我們真正的爬蟲之旅了。
urllib庫
Python有一個內置的urllib
庫,可謂是爬蟲過程非常重要的一部分了。這個內置庫的使用就可以完成向伺服器發出請求並獲得網頁的功能,所以也是學習爬蟲的第一步了。
博主用的是Python3.x
,urllib
庫的結構相對於Python2.x
有一些出入,Python2.x
中使用的urllib2
和urllib
庫,而Python3.x
中合併成一個唯一的urllib
庫。
首先,我們來看看Python3.x的urllib庫都有什麼吧。
博主用的IDE是Pycharm
,編輯調試非常方便,很贊。 在控制台下輸入如下代碼:
>>importurllib>>dir(urllib)[__builtins__,__cached__, __doc__, __file__, __loader__, __name__, __package__,__path__, __spec__, error, parse, request, response]
可以看到urllib除了以雙下劃線開頭結尾的內置屬性外,還有4個重要的屬性,分別是error,parse,request,response。
在Python的urllib庫中doc開頭是這樣簡短描述的:
- Error:「Exception classesraised by urllib.」----就是由urllib舉出的exception類
- Parse:「Parse (absolute andrelative) URLs.」----解析絕對和相對的URLs
- Request:「An extensiblelibrary for opening URLs using a variety of protocols」 ----用各種協議打開URLs的一個擴展庫
- Response:「Response classesused by urllib.」----被urllib使用的response類
這4個屬性中最重要的當屬request
了,它完成了爬蟲大部分的功能,我們先來看看request
是怎麼用的。
request的使用
request請求最簡單的操作是用urlopen
方法,代碼如下:
import urllib.requestresponse = urllib.request.urlopen(http://python.org/)result = response.read()print(result)
運行結果如下:
b<!doctype html>
<!--[if lt IE 7]>...</body>
</html>
發現得到的運行結果竟然是亂碼!!別著急,這是因為編碼的問題,我們只需要將請求的類文件讀取再解碼就可以了。
修改代碼如下:
import urllib.requestresponse = urllib.request.urlopen(http://python.org/)result = response.read().decode(utf-8)print(result)
運行結果如下:
<!doctype html><!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8>..<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9">.. <!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]--><!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"<head> <meta charset="utf-8">...
得到的就是我們想要的html的網頁了,怎麼樣,簡單吧。
下面來介紹一下這個urlopen
方法和其中應用的參數。
urlopen方法
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TI MEOUT,*, cafile=None, capath=None, cadefault=False, context=None):
urlopen是request的其中一個方法,功能是打開一個URL,URL參數可以是一串字元串(如上例子中一樣),也可以是Request對象(後面會提到)。
- url:即是我們輸入的url網址,(如:http://www.xxxx.com/);
- data:是我們要發給伺服器請求的額外信息(比如登錄網頁需要主動填寫的用戶信息)。如果需要添加
data參
數,那麼是POST
請求,默認無data參數時,就是GET
請求; - 一般來講,data參數只有在
http協
議下請求才有意義 - data參數被規定為
byte object
,也就是位元組對象 - data參數應該使用標準的結構,這個需要使用
urllib.parse.urlencode()
將data進行轉換,而一般我們把data設置成字典格式
再進行轉換即可;data在以後實戰中會介紹如何使用
- timeout:是選填的內容,定義超時時間,單位是秒,防止請求時間過長,不填就是默認的時間;
- cafile:是指向單獨文件的,包含了一系列的
CA認證
(很少使用,默認即可); - capath:是指向文檔目標,也是用於
CA認
證(很少使用,默認即可); - cafile:可以忽略
- context:設置
SSL加密
傳輸(很少使用,默認即可);
它會返回一個類文件對象,並可以針對這個對象進行各種操作(如上例中的read操作,將html全部讀出來),其它常用方法還有:
- geturl(): 返回URL,用於看是否有重定向。
result = response.geturl()
結果: https://www.python.org/
- info():返回元信息,例如HTTP的
headers
。
result = response.info()
結果:
x-xss-protection: 1; mode=block
X-Clacks-Overhead: GNU Terry Pratchett
... Vary: Cookie Strict-Transport-Security: max-age=63072000;includeSubDomains- getcode():返回回復的
HTTP狀態碼
,成功是200
,失敗可能是503
等,可以用來檢查代理IP的可使用性。
result = response.getcode()
結果:200
Request方法
class Request: def __init__(self, url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None):
如上定義,Request是一個類,初始化中包括請求需要的各種參數:
url
,data
和上面urlopen
中的提到的一樣。headers
是HTTP請求
的報文信息,如User_Agent
參數等,它可以讓爬蟲偽裝成瀏覽器
而不被伺服器發現你正在使用爬蟲。origin_reg_host
,unverifiable
,method
等不太常用
headers很有用,有些網站設有反爬蟲機制,檢查請求若沒有headers就會報錯,因此博主為保證爬蟲的穩定性,基本每次都會將headers信息加入進去,這是反爬的簡單策略之一。
那麼如何找到你所在瀏覽器的headers呢?
可以通過進入瀏覽器F12
查看到 比如,博主用的Chrome瀏覽器,按F12->network
就可以查看request的headers
,可以把這個瀏覽器的headers信息複製下來使用。
下面來看看Request如何使用吧,代碼如下:
import urllib.requestheaders = {User_Agent: }response = urllib.request.Request(http://python.org/, headers=headers)html = urllib.request.urlopen(response)result = html.read().decode(utf-8)print(result)
結果和前面urlopen
是一樣的,前面提到urlopen
除了可以接受指定參數,也可以接受Request類的對象。 裡面填寫自己瀏覽器的信息即可。
urllib庫的requset屬性裡面還有很多其它方法,代理
、超時
、認證
、HTTP的POST
模式下請求等內容將在下次進行分享,這次主要介紹基本功能。
下面來說說異常,urllib庫的error
方法。
error的使用
error
屬性裡面主要包括了兩個重要的exception類
,URLError類
和HTTPError類
。
1. URLError類
def __init__(self, reason, filename=None): self.args = reason, self.reason = reason if filename is not None: self.filename = filename
URLError類
是OSError
的子類,繼承OSError
,沒有自己的任何行為特點,但是將作為error裡面所有其它類型的基類使用。URLError類
初始化定義了reason
參數,意味著當使用URLError類的對象時,可以查看錯誤的reason。
2. HTTPErro類
def __init__(self, url, code, msg, hdrs, fp): self.code = code self.msg = msg self.hdrs = hdrs self.fp = fp self.filename = url
HTTPError
是URLError
的子類,當HTTP發生錯誤將舉出HTTPError
。HTTPError
也是HTTP有效回應的實例,因為HTTP協議錯誤是有效的回應,包括狀態碼
,headers
和body
。所以看到在HTTPError
初始化的時候定義了這些有效回應的參數。- 當使用
HTTPError
類的對象時,可以查看狀態碼,headers
等。
下面我們用一個例子來看一下如何使用這兩個exception
類。
import urllib.requestimport urllib.errortry: headers = {User_Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0} response = urllib.request.Request(http://python.org/, headers=headers) html = urllib.request.urlopen(response) result = html.read().decode(utf-8)except urllib.error.URLError as e: if hasattr(e, reason): print(錯誤原因是 + str(e.reason))except urllib.error.HTTPError as e: if hasattr(e, code): print(錯誤狀態碼是 + str(e.code))else: print(請求成功通過。)
以上代碼使用了try..exception
的結構,實現了簡單的網頁爬取,當有異常時,如URLError
發生時,就會返回reason
,或者HTTPError
發生錯誤時就會返回code
。異常的增加豐富了爬取的結構,使其更加健壯。
為什麼說更加健壯了呢?
不要小看了這些異常的錯誤,這些異常的錯誤非常好用,也非常關鍵。想想看,當你編寫一個需要不斷自動運行爬取並解析的代碼時,你是不希望程序中間被打斷而終止的。如果這些異常狀態沒有設置好,那麼就很有可能彈出錯誤而被終止,但如果設置好了完整的異常,則遇到錯誤時就會執行發生錯誤的代碼而不被打斷(比如向上面代碼一樣列印錯誤code
等)。
這些打斷程序的錯誤可能是很多種,尤其當你使用代理ip池
的時候,會發生很多不同錯誤,這時異常就起到作用了。
4. 總結
- 介紹了爬蟲的定義和學習路線
- 介紹了爬蟲的過程
- 介紹開始爬蟲學習的urllib庫的使用,包含以下幾個方法:
- request請求: urlopen, Request
- error異常
關注微信公眾號Python數據科學,帶你走進數據的世界。
推薦閱讀:
※利用requests爬取表情包
※Python爬取拉勾網所有的職位信息(一)
※case1: 爬取豆瓣top250排行榜的所有電影的信息
※解讀爬蟲中HTTP的秘密(基礎篇)
TAG:python爬蟲 |