【0基礎學爬蟲】爬蟲基礎之網路請求庫的使用

K哥爬蟲發表於2023-03-26

0

大資料時代,各行各業對資料採集的需求日益增多,網路爬蟲的運用也更為廣泛,越來越多的人開始學習網路爬蟲這項技術,K哥爬蟲此前已經推出不少爬蟲進階、逆向相關文章,為實現從易到難全方位覆蓋,特設【0基礎學爬蟲】專欄,幫助小白快速入門爬蟲,本期為網路請求庫的使用。

網路請求庫概述

作為一名爬蟲初學者,熟練使用各種網路請求庫是一項必備的技能。利用這些網路請求庫,我們可以透過非常簡單的操作來進行各種協議的模擬請求。我們不需要深入底層去關注如何建立通訊與資料如何傳輸,只需要呼叫各種網路請求庫封裝好的方法。Python提供了很多功能強大的網路請求庫,如urllib、requests、httpx、aiohttp、websocket等,下文中會對這些庫做一一介紹。

urllib

安裝與介紹

安裝

urllib是Python的內建請求庫,不需要再額外安裝。

介紹

urllib庫包含四個模組:

urllib.request: 向目標url發起請求並讀取響應資訊。

urllib.error: 負責異常處理,捕獲urllib.request丟擲的異常。

urllib.parse: 解析url,提供了一些url的解析方法。

urllib.robotparser: 解析網站robots.txt檔案,判斷網站是否允許爬蟲程式進行採集。

1

使用方法

請求與響應

使用到了urllib.request模組中的urlopen方法來開啟一個url並獲取響應資訊。urlopen預設返回的是一個HTTPResponse物件,可以透過read方法得到它的明文資訊。

import urllib.request

response = urllib.request.urlopen('http://httpbin.org/get')

print(response)  #列印:<http.client.HTTPResponse object at 0x0000013D85AE6548>
print(response.read().decode('utf-8'))  #響應資訊
print(response.status)                  #返回狀態碼
print(response.getheaders())            #返回響應頭資訊

設定請求頭與引數

當請求需要設定請求頭時,就需要用到urllib.request模組中的另一個方法Request,它允許傳遞如下幾個引數:

def __init__(self, url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None)

url:目標url

data:請求引數,預設為None

headers:請求頭資訊,字典型別

origin_req_host:請求的主機地址

unverifiable:設定網頁是否需要驗證

method:請求方式

from urllib import request,parse

url = 'https://httpbin.org/post'  #目標URL
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}                           #請求頭資訊
params = {
    'test':'test01'         #請求引數
}

data = bytes(parse.urlencode(params),encoding='utf-8')  #解析為bytes型別
res = request.Request(url,data=data,headers=headers,method='POST')  #例項化Request
response = request.urlopen(res)         #發起請求

print(response.read().decode('utf-8'))  #響應資訊

異常捕獲

在發起請求時,可能會因為網路、url錯誤、引數錯誤等問題導致請求異常,程式報錯。為了應對這種情況,我們需要新增異常處理功能。

from urllib import request,error

try:
    response = request.urlopen('http://httpbin.org/get')
except error.HTTPError as e:    #捕獲異常
    print(e)  #列印異常資訊

requests

requests是Python爬蟲開發中最常使用到的庫,它提供了簡單易用的API,使得在Python中傳送HTTP請求變得非常容易,它比urllib模組更加簡潔,使用更加方便。

安裝與介紹

安裝

requests是Python的第三方庫,使用 pip install requests 進行安裝

介紹

requests包含了許多模組,這裡只介紹主要模組:

requests: 主模組,提供了HTTP請求方法。

requests.session: 會話模組,提供了Session類,用於多個請求中共享請求資訊。

requests.adapters: 介面卡模組,提供了不同協議的介面卡類,用於處理不同協議的請求。

requests.cookie: Cookie模組,用於處理cookie資訊。

requests.exceptions: 異常處理模組,用於處理請求中會出現的各種異常。

requests.status_codes: 狀態碼模組,提供了HTTP狀態碼常量和狀態碼解釋。

使用方法

請求與響應

import requests   #匯入requests模組

get_response = requests.get('http://httpbin.org/get')   #傳送get請求
post_response = requests.post('http://httpbin.org/post')   #傳送post請求

print(get_response)   #<Response [200]>
print(post_response)   #<Response [200]>

requests庫傳送請求非常簡單,並支援多種請求方式,如:get、post、put、delete等。發起請求後requests會返回一個Response物件,可以使用多種方法來解析Response物件。

import requests

response = requests.get('http://httpbin.org/get')

print(response.status_code)   #返回響應狀態碼
print(response.encoding)   #返回響應資訊的編碼
print(response.text)   #返回響應的文字資訊
print(response.content)   #返回響應的位元組資訊
print(response.json())   #將JSON響應資訊解析為字典,如果響應資料型別不為JSON則會報錯
print(response.headers)   #返回響應頭資訊
print(response.cookies)   #返回響應cookie

設定請求頭與引數

request(self,method,url,params=None,data=None,headers=None,cookies=None,files=None,auth=None,timeout=None,allow_redirects=True,proxies=None,hooks=None,stream=None,verify=None,cert=None,json=None)

requests中設定請求頭可以透過headers引數來設定,headers是一個字典型別,鍵為請求頭的欄位名,值為對應請求頭的值。

請求引數可以透過params方法進行設定,型別為字典。鍵為引數名,值為對應引數的值。

在網路請求中,攜帶的引數可以分為兩個型別,它們在python中對應的欄位名如下:

查詢字串引數: params

請求載荷: data/json

查詢字串引數params是拼接在url中的引數,常用於get請求,作為查詢引數使用。而data與json一般使用與post請求中,它是要傳送到伺服器的實際資料。

import requests

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
}

params = {'key':'value'}
data = {'username':'user','passowrd':'password'}

get_response = requests.get(url,params=params,headers=headers)
post_response = requests.post(url,data=data,headers=headers)

Session的使用

當一個網站我們需要多次請求時,如我需要登入 -> 請求個人頁面,在面對這種場景時,我們可以使用到Session方法。因為透過requests傳送到的請求是獨立,我們請求登入介面與請求個人頁面之間是沒有聯絡的,我們需要請求登入介面後獲取它返回的cookie,然後設定cookie進行下一次請求。每次請求後都需要設定一次cookie,如果請求流程更多的話那麼過程就會顯得很繁瑣。使用Session方法就能更好的模擬一次請求流程,不需要頻繁的設定cookie。

Session的作用類似於瀏覽器中的cookie與快取,它可以用於在多次請求中維護一些狀態資訊,避免重複傳送相同的資訊和資料,使用Session可以最佳化HTTP請求的效能與可維護性,它的使用也非常簡單。

import requests

session = requests.Session()       #建立session物件
session.get('http://httpbin.org/cookies/set/username/test')   #發起請求,模擬一次登入
response = session.get('http://httpbin.org/cookies')   #獲取cookie

print(response.text)   #{"cookies": {"username": "test"}}

異常捕獲

requests.exceptions 中提供了一系列請求異常。

ConnectTimeout:連線超時

ReadTimeout:伺服器在指定時間內沒有應答

ConnectionError:未知的伺服器

ProxyError:代理異常

URLRequired:無效URL

TooManyRedirects:重定向過多

MissingSchema:URL缺失,如缺少:http/https

InvalidSchema:提供的URL方案無效或不受支援

InvalidURL:提供的URL不知何故無效

InvalidHeader:提供的請求頭無效

InvalidProxyURL:提供的代理URL無效

ChunkedEncodingError:伺服器宣告瞭編碼分塊,但傳送了無效分塊

ContentDecodingError:無法對響應資訊解碼

StreamConsumedError:此響應內容已被使用

RetryError:自定義重試邏輯錯誤

UnrewindableBodyError:請求在嘗試倒帶正文時遇到錯誤

HTTPError:出現HTTP錯誤

SSLError:發生SSL錯誤

Timeout:請求超時

httpx

前面講到了requests庫,它功能強大、使用簡單,並且提供session會話模組,似乎requests庫已經可以滿足所有的應用場景了。但是requests也有一些致命的缺點:

  1. 同步請求,不支援非同步,requests預設使用同步請求,在網路請求中同步請求到導致效能問題。
  2. 不支援HTTP2.0,如今已經有少部分網站採用HTTP2.0協議來進行資料傳輸,面對這類網站無法使用requests。

而httpx是一個基於非同步IO的Python3的全功能HTTP客戶端庫,旨在提供一個快速、簡單、現代化的HTTP客戶端,它提供同步與非同步API,而且支援HTTP1.1和HTTP2.0。並且httpx功能也很齊全,requests支援的功能httpx也基本同樣支援。因此,在爬蟲開發中使用httpx也是一個非常不錯的選擇。

安裝與介紹

安裝

httpx是Python的第三方庫,使用 pip install httpx 進行安裝

如果需要httpx支援https2.0,則需要安裝它的可選依賴項, pip install httpx[http2]

介紹

httpx是建立在requests的成熟可用性之上的,提供的模組與requests大同小異,因此不做介紹。

使用方法

httpx用法與requests基本一致,這裡主要介紹httpx的Client例項。

httpx Client

Client作用與requests的session方法一致,但用法有些區別。

常見用法是使用上下文管理器,這樣可以確保在請求完成後能夠正確清理連線。

import httpx

with httpx.Client() as client:
    response = client.get('https://httpbin.org/get')
    
print(response)   #<Response [200 OK]>

在設定請求頭、傳遞引數時也有新的寫法。

import httpx

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'}
params = {'key':'value'}

with httpx.Client(headers=headers,params=params) as client:
    response = client.get('https://httpbin.org/get')
    
print(response)

aiohttp

aiohttp是基於Python非同步IO的HTTP客戶端/伺服器庫,它與httpx相似,同樣支援HTTP1.1和HTTP2.0協議,aiohttp是基於asyncio實現的,它支援WebSocket協議。

安裝

aiohttp是Python的第三方庫,使用 pip install aiohttp 進行安裝

使用

import aiohttp
import asyncio

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://httpbin.org/get') as response:
            print(response) #<ClientResponse(https://httpbin.org/get) [200 OK]>

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

aiohttp不支援同步,需要與asyncio一起使用,與前文中講到的庫對比,aiohttp顯得異常複雜,requests兩行程式碼就能完成的功能aiohttp卻需要5行。為什麼aiohttp程式碼如此冗餘我們卻要使用它呢?因為aiohttp是非同步的,它的api旨在充分利用非阻塞網路操作,在例項程式碼中,請求將阻塞三次,這為事件迴圈提供了三次切換上下文的機會。aiohttp可以實現單執行緒併發IO操作,它在處理大量網站請求時的速度遠超於requests,但在涉及到檔案讀寫操作時,它發揮的作用就沒有預期的那麼大,因此aiohttp庫的使用需要爬蟲開發者自行斟酌。

websocket

Python websocket庫是專門用於建立WebSocket服務的庫。WebSocket是一種在客戶端與服務端之間進行雙向通訊的協議,服務端可以向客戶端推送資料,客戶端也可以向服務端推送資料,這樣就能實現資料的及時通訊,它與HTTP協議一樣,由socket實現。WebSocket通常使用在直播、彈幕等場景中。

安裝

websocket是Python的內建庫,不需要手動安裝。當你在執行下文中的例項時,如果報錯cannot import name 'WebSocketApp' from 'websocket',你可以解除安裝現有的websocket庫,安裝websocket-client==0.53.0版本的包。

使用

websocket用於客戶端與服務端通訊,爬蟲開發中一般只會進行客戶端的開發,所有這裡只介紹客戶端的開發。

使用WebSocketApp可以快速的建立一個Websocket連線。

from websocket import WebSocketApp

def on_message(ws, message):  #接收到訊息時執行
    print(message)
def on_error(ws, error):  #異常時執行
    print(error)
def on_close(ws):   #關閉連線時執行
    print("WebSocket closed")
def on_open(ws):  #開啟連線時執行
    ws.send("Hello, WebSocket!")  #傳送資訊
    
if __name__ == "__main__":
    ws = WebSocketApp("ws://echo.websocket.org/",
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close)
    ws.on_open = on_open
    ws.run_forever()

可以看到websocket提供了四個模組:

on_message: 接收伺服器推送來的資料

on_error: 連線異常時會觸發on_error

on_close: 連線關閉時觸發on_close

on_open: 連線開啟時觸發on_open

歸納

上文中講到了urllib、requests、httpx、aiohttp、websocket這五個庫的使用,這五個庫基本能夠滿足爬蟲開發中的請求需求。urllib是python的內建庫,使用起來較為繁瑣,可以只做瞭解。requests是爬蟲開發中最常使用的庫,功能齊全,使用簡單,需要認真學習。httpx在requests的基礎上支援非同步處理、HTTP2.0與Websocket協議,requests的功能httpx都支援,但在效能方面httpx弱於其他請求庫,httpx也需要爬蟲初學者好好學習。aiohttp用於編寫非同步爬蟲,開發效率低於其它庫,但是執行效率遠高與其它庫,也是一個需要好好掌握的請求庫。websocket是專門用於Websocket協議的庫,使用也較為簡單,可以在需要時再做了解。

相關文章