1. 程式人生 > >Python3之urllib庫的使用總結

Python3之urllib庫的使用總結

Urllib庫是Python中的一個功能強大、用於操作URL,並在做爬蟲的時候經常要用到的庫。在Python2.x中,分為Urllib庫和Urllin2庫,Python3.x之後都合併到Urllib庫中,使用方法稍有不同。本文介紹的是Python3中的urllib庫。

什麼是Urllib庫

Urllib是Python提供的一個用於操作URL的模組,我們爬取網頁的時候,經常需要用到這個庫。

升級合併後,模組中的包的位置變化的地方較多。在此,列舉一些常見的位置變動,方便之前用Python2.x的朋友在使用Python3.x的時候可以快速掌握。

常見的變化有:

  • 在Pytho2.x中使用import urllib2——-對應的,在Python3.x中會使用import urllib.request,urllib.error。
  • 在Pytho2.x中使用import urllib——-對應的,在Python3.x中會使用import urllib.request,urllib.error,urllib.parse。
  • 在Pytho2.x中使用import urlparse——-對應的,在Python3.x中會使用import urllib.parse。
  • 在Pytho2.x中使用import urlopen——-對應的,在Python3.x中會使用import urllib.request.urlopen。
  • 在Pytho2.x中使用import urlencode——-對應的,在Python3.x中會使用import urllib.parse.urlencode。
  • 在Pytho2.x中使用import urllib.quote——-對應的,在Python3.x中會使用import urllib.request.quote。
  • 在Pytho2.x中使用cookielib.CookieJar——-對應的,在Python3.x中會使用http.CookieJar。
  • 在Pytho2.x中使用urllib2.Request——-對應的,在Python3.x中會使用urllib.request.Request。

快速使用Urllib爬取網頁

以上我們對Urllib庫做了簡單的介紹,接下來講解如何使用Urllib快速爬取一個網頁。
首先需要匯入用到的模組:urllib.request

import urllib.request

在匯入了模組之後,我們需要使用urllib.request.urlopen開啟並爬取一個網頁,此時,可以輸入如下程式碼爬取百度首頁(www.baidu.com),爬取後,將爬取的網頁賦給了變數file:

>>>file=urllib.request.urlopen('www.baidu.com')

此時,我們還需要將對應的網頁內容讀取出來,可以使用file.read()讀取全部內容,或者也可以使用file.readline()讀取一行內容。

>>>data=file.read()    #讀取全部
>>>dataline=file.readline()    #讀取一行內容

讀取內容常見的有3種方式,其用法是:
1. read()讀取檔案的全部內容,與readlines()不同的是,read()會把讀取到的內容賦給一個字串變數。
2. readlines()讀取檔案的全部內容,readlines()會把讀取到的內容賦值給一個列表變數。
3. readline()讀取檔案的一行內容。

此時,我們已經成功實現了一個網頁的爬取,那麼我們如何將爬取的網頁以網頁的形式儲存在本地呢?
思路如下:
1. 爬取一個網頁並將爬取到的內容讀取出來賦給一個變數。
2. 以寫入的方式開啟一個本地檔案,命名為*.html等網頁格式。
3. 將步驟1中的變數寫入該檔案中。
4. 關閉該檔案

我們剛才已經成功獲取到了百度首頁的內容並讀取賦給了變數data,接下來,可以通過以下程式碼實現將爬取到的網頁儲存在本地。

>>>fhandle=open("./1.html","wb")
>>>fhandle.write(data)
>>>fhandle.close()

此時,1.html已竄在我們指定的目錄下,用瀏覽器開啟該檔案,就可以看到我們爬取的網頁介面。

除此之外,urllib中還有一些常見的用法。
如果希望返回與當前環境有關的資訊,我們可以使用info()返回,比如可以執行:

>>>file.info()
<http.client.HTTPMessage object at 0x0000000003623D68>

可以看到,輸出了對應的info,呼叫格式則為:“爬取的網頁.info()”,我們之前爬取到的網頁賦給了變數file,所以此時通過file呼叫。
如果我們希望獲取當前爬取網頁的狀態碼,我們可以使用getcode(),若返回200為正確,返回其他則不正確。在該例中,我們可以執行:

>>>file.getcode()
200

如果想要獲取當前所爬取的URL地址,我們可以使用geturl()來實現。

>>>file.geturl()
'http://www.baidu.com'

一般來說,URL標準中只會允許一部分ASCII字元比如數字、字母、部分符號等,而其他的一些字元,比如漢字等,是不符合URL標準的。此時,我們需要編碼。
如果要進行編碼,我們可以使用urllib.request.quote()進行,比如,我們如果要對百度網址進行編碼:

>>>urllib.request.quote('http://www.baidu.com')
'http%3A//www.baidu.com'

那麼相應的,有時候需要對編碼的網址進行解碼

>>>urllib.request.unquote('http%3A//www.baidu.com')
'http://www.baidu.com'

瀏覽器的模擬—Headers屬性

有的時候,我們無法爬取一些網頁,會出現403錯誤,因為這些網頁為了防止別人惡意採集其資訊所以進行了一些反爬蟲的設定。
那麼如果我們向爬取這些網頁的資訊,應該怎麼辦呢?
可以設定一些Headers資訊,模擬成瀏覽器去訪問這些網站,此時,就能夠解決這個問題了。
那我們該新增什麼頭部資訊呢?
我們需要讓爬蟲模擬成瀏覽器,模擬成瀏覽器可以設定User-Agent資訊。
任意開啟一個網頁,比如開啟百度。然後按F12,會出現一個視窗。切換到Network標籤頁:
然後單擊網頁中的“百度一下”,即讓網頁發生一個動作。
此時,我們可以觀察到下方的窗口出現了一些資料。將介面右上方的標籤切換到“Headers”中,即可以看到了對應的頭資訊,此時往下拖動,就可以找到User-Agent字樣的一串資訊。這一串資訊即是我們下面模擬瀏覽器所需要用到的資訊。我們將其複製出來。如圖:
這裡寫圖片描述

這裡寫圖片描述

我們可以得到該資訊:

User-Agent:Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
X-Requested-With:XMLHttpRequest

接下來,我們講解如何讓爬蟲模擬成瀏覽器訪問頁面的設定方法。

import urllib.request
import urllib.parse

url='http://www.baidu.com'
hearder={
   'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}

request=urllib.request.Request(url,headers=header)
reponse=urllib.request.urlopen(request).read()

fhandle=open("./1.html","wb")
fhandle.write(reponse)
fhandle.close()

首先,設定要爬取的網址,然後呼叫urllib.request.Request()函式建立一個request物件,該函式第一個引數傳入url,第二個引數可以傳入資料,預設是傳入0資料,第三個引數是傳入頭部,該引數也是有預設值的,預設是不傳任何頭部。
我們需要建立一個dict,將頭部資訊以鍵值對的形式存入到dict物件中,然後將該dict物件傳入urllib.request.Request()函式第三個引數。
此時,已經成功設定好報頭,然後我們使用urlopen()開啟該Request物件即可開啟對應的網址。

超時設定

有的時候,我們訪問一個網頁,如果該網頁長時間未響應,那麼系統就會判斷該網頁超時了,即無法開啟該網頁。
有的時候,我們需要根據自己的需要來設定超時的時間值。我們可以在urllib.request.urlopen()開啟網址的時候,通過timeout欄位設定。
設定格式為:urllib.request.urlopen(要開啟的網址,timeout=時間值)。

HTTP協議請求實戰

如果要進行客戶端與伺服器端之間的訊息傳遞,我們可以使用HTTP協議請求進行。
HTTP協議請求主要分為6種類型,各型別的主要作用如下:

  • GET請求:GET請求會通過URL網址傳遞資訊,可以直接在URL中寫上要傳遞的資訊,也可以由表單進行傳遞。如果使用表單進行傳遞,這表單中的資訊會自動轉為URL地址中的資料,通過URL地址傳遞。
  • POST請求:可以向伺服器提交資料,是一種比較主流也比較安全的資料傳遞方式,比如在登入時,經常使用POST請求傳送資料。
  • PUT請求:請求伺服器儲存一個資源,通常要指定儲存的位置。
  • DELETE請求:請求伺服器刪除一個資源。
  • HEAD請求:請求獲取對應的HTTP報頭資訊。
  • OPTIONS請求:可以獲取當前URL所支援的請求型別。

除此之外,還有TRACE請求與CONNECT請求等。
接下來,將通過例項講解HTTP協議請求中的GET請求和POST請求,這兩種請求相對來說用的最多。

GET請求示例分析

有時想在百度上查詢一個關鍵詞,我們會開啟百度首頁,並輸入該關鍵詞進行查詢,那麼這個過程怎樣使用爬蟲自動實現呢?
我們首先需要對查詢過程進行相應的分析,可以開啟百度首頁,然後輸入想檢索的關鍵詞,比如輸入“hello”,然後按回車鍵,我們觀察一下URL的變化,此時URL變成:

可以發現,對應的查詢資訊是通過URL傳遞的,這裡採用的就是HTTP請求中的GET請求方法,我們將該網址提取出來進行分析,欄位ie的值為utf8,代表的是編碼資訊,而欄位wd為hello,剛好是我們要查詢的資訊,所以欄位wd應該儲存的就是使用者檢索的關鍵詞。根據我們的猜測,化簡一下該網址,可以化簡為https://www.baidu.com/s?wd=hello,將該網址複製到瀏覽器中,重新整理一下,會發現該網址也能夠出現關鍵詞為‘hello’的搜尋結果。
由此可見,我們在百度上查詢一個關鍵字時,會使用GET請求,其中關鍵性欄位是wd,網址格式為:https://www.baidu.com/s?wd=關鍵詞
分析到這裡,你應該大概知道我們該怎麼用爬蟲實現自動地在百度上查詢關鍵詞結果了。直接上程式碼~

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import urllib.request
import urllib.parse

url='http://www.baidu.com/s?wd='
key='fengxin的部落格' 
key_code=urllib.request.quote(key)  #因為URL裡含中文,需要進行編碼
url_all=url+key_code
header={
    'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}   #頭部資訊
request=urllib.request.Request(url_all,headers=header)
reponse=urllib.request.urlopen(request).read()

fh=open("./baidu.html","wb")    #寫入檔案中
fh.write(reponse)
fh.close()

此時,我們用瀏覽器開啟剛才儲存的baidu.html檔案,我們就可以看到我們剛才爬取的網頁結果,如圖:
這裡寫圖片描述

通過以上例項我們可以知道,如果要使用GET請求,思路如下:

  • 構建對應的URL地址,該URL地址包含GET請求的欄位名和欄位內容等資訊,並且URL地址滿足GET請求的格式,即“http://網址?欄位名1=欄位內容1&欄位名2=欄位內容2”
  • 以對應的URL為引數,構建Request物件。
  • 通過urlopen()開啟構建的Request物件。
  • 按需求進行後續的處理操作,比如讀取網頁的內容、將內容寫入檔案等。

POST請求例項分析

我們在進行註冊、登入等操作的時候,基本上都會遇到POST請求,接下來我們就為大家通過例項來分析如何通過爬蟲來實現POST請求。
在此,我們示例一下如何使用爬蟲通過POST表單傳遞資訊。
給大家提供一個POST表單的測試網頁,做測試使用,網址為:
http://www.iqianyue.com/mypost
開啟網址,會發現有一個表單。
這裡寫圖片描述

如何通過爬蟲自動實現這個傳遞過程呢?
因為這裡所採用的傳遞方法是POST方法,所以如果要使用爬蟲自動實現,我們要構造PSOT請求,實現思路如下:

  • 設定好URL網址。
  • 構建表單資料,並使用urllib.parse.urlencode對資料進行編碼處理。
  • 構建Request物件,引數包括URL地址和要傳遞的資料。
  • 新增頭部資訊,模擬瀏覽器進行爬取。
  • 使用urllib.requesr.urlopen()開啟對應的Request物件。完成資訊的傳遞。
  • 後續處理,比如讀取網頁內容,將內容寫入檔案等。

首先,需要設定好對應的URL地址,分析該網頁,在單擊提交之後,會傳遞到當前頁面進行處理,所以處理的頁面應該是http://www.iqianyue.com/mypost,所以,URL應該設定為http://www.iqianyue.com/mypost
然後我們需要構建表單資料,在該網頁上右擊“檢視網頁原始碼”,找到對應的form表單部分,然後進行分析。如圖:
這裡寫圖片描述

可以發現,表單中的姓名對應的輸入框中,name屬性值為”name”,密碼對應的輸入框中,name屬性值為”pass”,所以,我們構造的資料中會包含兩個欄位,欄位名分別是”name”,”pass’。欄位值設定我們要傳遞的資訊。格式為字典形式,即:
{欄位名1:欄位值1,欄位名2:欄位值2,…..}
其他的跟上面的GET請求類似,直接上程式碼~

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import urllib.request
import urllib.parse

url='http://www.iqianyue.com/mypost'
header={
   'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}

data={'name':'fengxin','pass':'123'}
postdata=urllib.parse.urlencode(data).encode('utf8') #進行編碼
request=urllib.request.Request(url,postdata)
reponse=urllib.request.urlopen(request).read()

fhandle=open("./1.html","wb")
fhandle.write(reponse)
fhandle.close()

在瀏覽器中開啟我們剛儲存的1.html檔案,可以看到,資料已經成功提交。
這裡寫圖片描述