Python爬蟲學習之(一)| 從零開始

做者:xiaoyu
微信公衆號:Python數據科學
知乎:Python數據分析師html


你們好,相信點進來看的小夥伴都對爬蟲很是感興趣,博主也是同樣的。博主剛開始接觸爬蟲的時候,就被深深吸引了,由於感受SO COOL啊!每當敲完代碼後看着一串串數據在屏幕上浮動,感受頗有成就感,有木有?更厲害的是,爬蟲的技術能夠應用到不少生活場景中,例如,自動投票啊,批量下載感興趣的文章、小說、視頻啊,微信機器人啊,爬取重要的數據進行數據分析啊,切實的感受到這些代碼是給本身寫的,能爲本身服務,也能爲他人服務,因此人生苦短,我選爬蟲。前端

說實在的,博主也是個朝九晚五的上班族,學習爬蟲也是利用業餘時間,但就憑着對爬蟲的熱情開始了爬蟲的學習之旅,俗話說嘛,興趣是最好的老師。博主也是一個小白,開這個公衆號的初衷就是想和你們分享一下我學習爬蟲的一些經驗以及爬蟲的技巧,固然網上也有各類各樣的爬蟲教程均可供你們參考學習,在後面博主會分享一些開始學習時用到的資源。好了,不廢話了,開始咱們的正題。python

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、動態網頁等問題
  • 瞭解爬蟲與數據庫的結合,如何將爬取數據進行儲存
  • 學習應用Python的多線程、多進程進行爬取,提升爬蟲效率
  • 學習爬蟲的框架,Scrapy、PySpider等
  • 學習分佈式爬蟲(數據量龐大的需求)

以上即是一個總體的學習概況,好多內容博主也須要繼續學習,關於提到的每一個步驟的細節,博主會在後續內容中以實戰的例子逐步與你們分享,固然中間也會穿插一些關於爬蟲的好玩內容。網絡

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.request
response = urllib.request.urlopen('http://python.org/')
result = response.read()
print(result)

運行結果以下:

b'<!doctype html>\n<!--[if lt IE 7]>...</body>\n</html>\n'

發現獲得的運行結果居然是亂碼!!彆着急,這是由於編碼的問題,咱們只須要將請求的類文件讀取再解碼就能夠了。

修改代碼以下:

import urllib.request
response = 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.request
headers = {'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.request
import urllib.error
try:
    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數據科學,獲取 120G 人工智能 學習資料。
圖片描述

圖片描述

相關文章
相關標籤/搜索