小白學 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

示例代碼-Gitee


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM