1. 程式人生 > >小白學 Python 爬蟲(11):urllib 基礎使用(一)

小白學 Python 爬蟲(11):urllib 基礎使用(一)

人生苦短,我用 Python

前文傳送門:

小白學 Python 爬蟲(1):開篇

小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝

小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門

小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門

小白學 Python 爬蟲(5):前置準備(四)資料庫基礎

小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝

小白學 Python 爬蟲(7):HTTP 基礎

小白學 Python 爬蟲(8):網頁基礎

小白學 Python 爬蟲(9):爬蟲基礎

小白學 Python 爬蟲(10):Session 和 Cookies

引言

看到本篇實戰的同學有沒有很激動,經過了前面十篇基礎內容的折磨,終於等到實戰章節了,有沒有一種激動之情。

想到一句歌詞:終於等到你~~~

首先,官方文件地址敬上:

官方文件地址:https://docs.python.org/3/library/urllib.html

在前面的前置準備中,我們一起安裝了很多第三方的請求類庫,在介紹這些第三方的類庫前,我們先介紹一下 Python3 本身自帶的一個 HTTP 請求庫 urllib 。

urllib

urllib 是一個軟體包,它包含了幾個用於處理 URL 的模組:

  • request: 基礎的 HTTP 請求模組。
  • error: 異常處理模組。
  • parse: 用於解析 URL 的模組。
  • robotparser: 識別網站中 robots.txt 檔案。

urllib.request

如果要說怎麼學習最快,當然是檢視官方文件,首先祭出官方文件的地址。

urllib.request官方文件: https://docs.python.org/3/library/urllib.request.html#module-urllib.request

這裡的解釋是最權威了,並且目前已經提供了中文版本,不過那個翻譯看起來像是機器翻譯的,質量並不高。

如果實在看不懂,就只能看小編 XBB 了。

urlopen

urllib.request 模組提供了最基本的構造 HTTP 請求的方法,使用它可以模擬瀏覽器的一個請求發起過程,同時它還帶有處理授權驗證(authenticaton)、重定向(redirection)、瀏覽器Cookies以及其他內容。

語法:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

這麼厲害的模組當然是要趕緊嘗試一下,首先我們使用它爬取一下小編的部落格站:

import urllib.request

response = urllib.request.urlopen('https://www.geekdigging.com/')
print(response.read().decode('utf-8'))

執行結果小編這裡就不展示,比較長。

短短的三行程式碼,我們就完成了網站原始碼的抓取,是不是很簡單。

當我們得到原始碼之後,想要的連結、文字資訊,都可以從中提取出來。

各位同學看到列印的內容,可以猜測一下這個內容是什麼資料型別,會是字串型別麼?

使用 type() 看一下就知道了。

print(type(response))

結果:

<class 'http.client.HTTPResponse'>

urlopen 返回了一個 HTTPResponse 型別的物件。

官方文件對 HTTPResponse 的解釋如下:

An HTTPResponse instance wraps the HTTP response from the server. It provides access to the request headers and the entity body. The response is an iterable object and can be used in a with statement.

大意是說 HTTPResponse 是對 HTTP 響應的包裝。它提供了對請求頭和請求體的訪問。這個響應是一個可以迭代的物件。

HTTPResponse 主要包含 read() 、 readline() 、 getheader(name) 、 getheaders() 、 fileno() 等方法,以及 msg 、 version 、 status 、 reason 、 debuglevel 、 closed 等屬性。

import urllib.request

# 獲取HTTP協議版本號(10 for HTTP/1.0, 11 for HTTP/1.1)
print(response.version)

# 獲取響應碼
print(response.status)
print(response.getcode())

# 獲取響應描述字串
print(response.reason)

# 獲取實際請求的頁面url(防止重定向用)
print(response.geturl())

# 獲取特定響應頭資訊
print(response.getheader(name="Content-Type"))
# 獲取響應頭資訊,返回二元元組列表
print(response.getheaders())
# 獲取響應頭資訊,返回字串
print(response.info())

# 讀取響應體
print(response.readline().decode('utf-8'))

結果有點長,小編就不貼了,各位同學可以自己執行一下。

data

data 用來指明發往伺服器請求中的額外的引數資訊, data 預設是 None ,此時以 GET 方式傳送請求;當用戶給出 data 引數的時候,改為 POST 方式傳送請求。

來個示例吧,這裡我們使用 httpbin 提供的測試介面,此專案為 postmanlabs 提供在 Github開源的專案, Github 地址為:https://github.com/postmanlabs/httpbin 。

import urllib.request
import urllib.parse

post_data = bytes(urllib.parse.urlencode({'name': 'geekdigging', 'hello':'world'}), encoding='utf8')
response = urllib.request.urlopen('https://httpbin.org/post', data = post_data)
print(response.read().decode('utf-8'))

值得注意的是,這裡我們傳遞了兩個引數,是以 dict 的方式傳遞的,它一定需要被轉碼成 bytes 位元組流, 這裡使用了 bytes() 方法,第一個引數是我們需要轉換的字串,第二個引數是編碼方式。

這裡我們請求的路徑是 https://httpbin.org/post ,這個連結可以用來測試 POST 請求,它可以返回一些我們剛才請求的資訊。

響應結果如下:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "hello": "world", 
    "name": "geekdigging"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "28", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.7"
  }, 
  "json": null, 
  "origin": "218.79.141.143, 218.79.141.143", 
  "url": "https://httpbin.org/post"
}

從返回的響應資訊中,我們可以看到請求頭的相關資訊,如我們請求的資料型別 Content-Typeapplication/x-www-form-urlencoded ,這個代表了我們提交資料的方式是表單提交,還可以看到請求的來源 origin 是小編當前電腦的 ip 地址,可以看到我們提交的資料 form 等等的相關資訊。

timeout

timeout 用於設定超時時間,單位為秒。

如果請求超出了設定的時間,還未響應,就會丟擲異常。

我們看個小示例:

import urllib.request
import urllib.parse

response = urllib.request.urlopen('http://httpbin.org/get', timeout = 1)
print(response.read().decode('utf-8'))

我們先將超時時間設定成為 1s ,看下響應結果:

{
  "args": {}, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.7"
  }, 
  "origin": "218.79.141.143, 218.79.141.143", 
  "url": "https://httpbin.org/get"
}

可以看到是正常響應的,我們將超時時間設定為 0.1s ,再看下結果:

import urllib.request
import urllib.parse

response = urllib.request.urlopen('http://httpbin.org/get', timeout = 0.1)
print(response.read().decode('utf-8'))

已經可以看到拋異常出來了:

Traceback (most recent call last):
...
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
...
urllib.error.URLError: <urlopen error timed out>

Process finished with exit code 1

內容有些多,小編省略了大量的內容。

我們可以看到,這裡確實丟擲了超時的異常,還有同學記得我們前面講過的異常處理麼,這時我們可以新增一個異常處理,將這個超時的異常捕獲。

import urllib.request
import urllib.error
import socket

try:
    response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
    print(response.read().decode('utf-8'))
except urllib.error.URLError as e:
    if isinstance(e.reason, socket.timeout):
        print('請求超時啦~~~')
    else:
        print(e)

結果如下:

請求超時啦~~~

證明我們已經成功捕獲到了請求超時的異常。

還有其他的幾個引數: cafilecapathcadefault 用於實現可信任的 CA 證書的 HTTP 請求,一般很少使用, context ,用來實現 SSL 加密傳輸,一般也很少使用。

好了,本篇的內容就到這裡結束,希望各位同學可以自己動手敲一下上面的示例程式碼。

示例程式碼

本系列的所有程式碼小編都會放在程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gi