天天看點

python爬蟲第1章 urllib庫(一) urllib庫概述python爬蟲第1章 urllib庫(一) urllib庫概述

python爬蟲第1章 urllib庫(一) urllib庫概述

urllib是一個模拟浏覽器發送請求的庫,是python内置的庫,不需要額外的安裝。

python2中分為:urllib urllib2

python3中被合并為urllib,urllib.request、urllib.parse分别對應于urllib、urllib2。

在python3中分成了三個子產品:

  1. urllb.request 請求子產品
  2. urllib.parse 解析子產品
  3. urllib.error 異常處理子產品

一、urllib.request子產品

該子產品中的主要方法:

方法 示例
urllib.request.urlopen response = urllib.request.urlopen(r"https://www.baidu.com") # 傳入url,得到HTTPResponse響應對象
urllib.request.urlretrieve urllib.request.urlretrieve(r"https://www.baidu.com", “baidu.html”) # 傳入url、檔案路徑,直接将響應資料儲存在本地

響應對象response(http.client.HTTPResponse對象)的主要方法:

方法 描述
response.read() 讀取響應體,内容是位元組類型 。可通過response.read().decode()轉為字元串
response.geturl() 擷取請求的url
response.getheaders() 擷取頭部資訊,是清單。可通過dict(list1) 轉為字典以便取值
response.getcode() 擷取響應狀态碼
response.readlines() 按行讀取,傳回清單,都是位元組類型

(一)urllib.request.urlopen方法示例

import urllib.request

url = r"https://www.baidu.com"
response = urllib.request.urlopen(url)

print(response) # 列印:<http.client.HTTPResponse object at 0x00000219BC7B56A0>

print(response.read()) # 列印二進制

print(response.read().decode()) # 将二進制轉為字元串進行列印

# 将響應資料寫入檔案
with open("baidu.html","w",encoding="utf-8") as f:
    f.write(response.read().decode())
#注意:response.read()隻能讀取一次,第二次就讀取不到了

           

(二)urlopen和urlretrieve異同:以下載下傳一張圖檔為例

import urllib.request

url =r"https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_86d58ae1.png"

response  = urllib.request.urlopen(url)

with open("chushiyan.jpg","wb") as f:
    f.write(response.read())
           
import urllib.request

url = r"https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo_top_86d58ae1.png"

urllib.request.urlretrieve(url, "chushiyan1.jpg")
           

從上面案例看出,同樣下載下傳一張圖檔,urlretrieve方法更簡潔一些。

二、urllib.parse子產品

url隻能由特定的字元組成:字母、數字、下劃線。如果出現其他的,如:$、空格、漢字等,就要進行編碼。urllib.parse子產品就是幹這個的。

(一)主要方法

方法 描述
urllib.parse.quote(url) url編碼。注:quote v.引述;舉證 n. 引用
urllib.parse.unquote(url) url解碼
urllib.parse.urlencode(dict2) 傳入一字典,将字典拼接為url查詢部,并完成url編碼

(二)主要方法的使用示例

1、urllib.parse.quote()和urllib.parse.unquote()

import urllib.parse
url = r"http://www.baidu.com/index.html?name=張三&password=123456"

# 1、url編碼
url = urllib.parse.quote(url)
print(url)
# 輸出:http%3A//www.baidu.com/index.html%3Fname%3D%E5%BC%A0%E4%B8%89%26password%3D123456

# 2、url解碼
print(urllib.parse.unquote(url))
# 輸出:http://www.baidu.com/index.html?name=張三&password=123456

           

2、urllib.parse.urlencode()

先看看,不使用urllib.parse.urlencode()時,如何對參數組成的字典進行url編碼:

import urllib.parse
url = r"http://www.baidu.com"

date = {
    "name":"張三",
    "age":25,
    "gender":"nan",
    "stature":175
}
list2 = []
for k,v in date.items():
    list2.append(k+"="+str(v))

query_string = "&".join(list2)

url = url + "?"+query_string;
url = urllib.parse.quote(url)

print(url)

           

使用urlencode()函數時:

import urllib.parse
url = r"http://www.baidu.com"

date = {
    "name":"張三",
    "age":25,
    "gender":"nan",
    "stature":175
}

query_string = urllib.parse.urlencode(data)

url = url + "?" +query_string

print(url)
           

輸出同樣的結果:

http%3A//www.baidu.com%3Fname%3D%E5%BC%A0%E4%B8%89%26
age%3D25%26gender%3Dnan%26stature%3D175
           

(三)綜合案例

案例:讓使用者輸入需要搜尋的關鍵字,下載下傳儲存該搜尋結果頁面。

百度搜尋的url示例:http://www.baidu.com/s?wd=chushiyan

import urllib.request
import urllib.parse

word = input("請輸入您需要搜尋的内容...")
url = r"http://www.baidu.com/s?"

data= {
    "wd":word
}

query_string = urllib.parse.urlencode(data)
url +=  query_string

urllib.request.urlretrieve(url,word+".html")
           

三、urllib.error子產品

異常類:URLError、HTTPError。前者是後者的父類。都位于urllib.error子產品中(error.py檔案)。

發生URLError異常的情況:

(1)沒有網絡

(2)伺服器連接配接失敗

(3)找不到指定的伺服器

HTTPError異常:

HTTP 錯誤可能是“404 Page Not Found”、“500 Internal Server Error”等。所有類似情形, urlopen 函數都會抛出“HTTPError”異常。

注:兩個異常同時捕獲時,需要将HTTPError寫在前面,URLError寫在後面。

import urllib.request
import urllib.parse
import urllib.error

# 定義一個不存在的url
url = r"http://chushiyan.org"

try:
    response = urllib.request.urlopen(url)
    print(response)

except urllib.error.HTTPError as e:
    print(e)
except urllib.error.URLError as e:
    print(e) #列印:<urlopen error [Errno 11001] getaddrinfo failed>