HTTP請求:requests的進階使用方法淺析

来源:https://www.cnblogs.com/Jcloud/archive/2023/06/16/17486070.html
-Advertisement-
Play Games

上篇文章講解了requests模塊的基礎使用,其中有get、put、post等多種請求方式,使用data、json等格式做為請求參數,在請求體中添加請求頭部信息的常見信息,如:headers、cookies,以及對請求響應的處理方法。接下來講解一下requests的高級用法。 ...


1 背景

上篇文章講解了requests模塊的基礎使用,其中有get、put、post等多種請求方式,使用data、json等格式做為請求參數,在請求體中添加請求頭部信息的常見信息,如:headers、cookies,以及對請求響應的處理方法。接下來講解一下requests的高級用法。

2 進階方法舉例

2.1 requests.request()

method:提交方式(get|post);

url:提交地址;

kwargs:14個控制訪問的參數;

常用的參數有:params、data、json、headers、cookies,已在上篇文章中介紹過了,感興趣的朋友,可以到上篇文章再回顧一下。以下將講解與示例其他參數的使用。

示例:

2.1.1 files

請求攜帶文件,如果有的請求需要上傳文件,可以用它來實現。

import requests

# 上傳文件
f= {"files": open("favicon.ico", "rb") }
data = {"name": "上傳文件"}

requests.request(
    method = 'POST', 
    url = 'http://127.0.0.1:8080/example/request',  
    data = data,
    files = f
)

需註意:favicon.ico文件需和當前腳本在同一目錄下,如果不在,可以將文件名稱修改為文件路徑

import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth

# 1、Basic Auth認證
res = requests.request(
    method = 'GET',
    url = 'http://127.0.0.1:8080/example/request',
    auth = HTTPBasicAuth("username", "password")
)
res.encoding = "gbk"

print(res.status)  # 200


# 2、DIGEST 認證
res = requests.request(
    method = 'GET',
    url = 'http://127.0.0.1:8080/example/request',
    auth = HTTPDigestAuth("username", "password")
)
res.encoding = "gbk"

print(res.status)  # 200

http auth認證的兩種方式,分別為Basic方式和Digest認證,其中:Basic Auth的優點是提供簡單的用戶驗證功能,其認證過程簡單明瞭,適合於對安全性要求不高的系統或設備中;同樣存在缺點:輸入的用戶名,密碼 base64編碼後會出現在Authorization里,很容易被解析出來。

那麼Digest對比Basic認證有什麼不同呢?

  • Digest思想,是使用一種隨機數字元串,雙方約定好對哪些信息進行哈希運算,即可完成雙方身份的驗證。Digest模式避免了密碼在網路上明文傳輸,提高了安全性,但它依然存在缺點,例如認證報文被攻擊者攔截到攻擊者可以獲取到資源。
  • DIGEST 認證提供了高於 BASIC 認證的安全等級,但是和 HTTPS 的客戶端認證相比仍舊很弱。
  • DIGEST 認證提供防止密碼被竊聽的保護機制,但並不存在防止用戶偽裝的保護機制。
  • DIGEST 認證和 BASIC 認證一樣,使用上不那麼便捷靈活,且仍達不到多數 Web 網站對高度安全等級的追求標準。因此它的適用範圍也有所受限。

2.1.2 timeout

請求和響應的超時時間,在網路響應延遲或者無響應時,可以通過設置超時時間,避免等待。

import requests

# 設置請求超時1秒,1秒後無響應,將拋出異常,1秒為connect和read時間總和
requests.request(
    method = 'POST',
    url = 'http://127.0.0.1:8080/example/request',
    json = {'k1' : 'v1', 'k2' : 'v2'},
    timeout = 1
)

# 分別設置connect和read的超時時間,傳入一個數組
requests.request(
    method = 'POST',
    url = 'http://127.0.0.1:8080/example/request',
    json = {'k1' : 'v1', 'k2' : 'v2'},
    timeout = (5, 15)
)

# 永久等待
requests.request(
    method = 'POST',
    url = 'http://127.0.0.1:8080/example/request',
    json = {'k1' : 'v1', 'k2' : 'v2'},
    timeout = None
    # 或者刪除timeout參數
)

# 捕捉超時異常
from requests.exceptions import ReadTimeout
try:
    res = requests.get('http://127.0.0.1:8080/example/request', timeout=0.1)
    print(res.status_code)
except ReadTimeout:
    print("捕捉到超時異常")

2.1.3 allow_redirects

設置重定向開關。

>>> import requests
>>> r = requests.get('http://github.com')
>>> r.url
'https://github.com/'

>>> r.status_code
200

>>> r.history
[<Response [301]>]

# 如果使用GET、OPTIONS、POST、PUT、PATCH或DELETE,則可以使用allow_redirects參數禁用重定向
>>> r = requests.get('http://github.com', allow_redirects=False)

>>> r.status_code
301

>>> r.history
[]

# 用HEAD啟動重定向
>>> r = requests.head('http://github.com', allow_redirects=True)

>>> r.url
'https://github.com/'

>>> r.history
[<Response [301]>]


import requests
import re

# 第一次請求
r1=requests.get('https://github.com/login')
r1_cookie=r1.cookies.get_dict() #拿到初始cookie(未被授權)
authenticity_token=re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0] #從頁面中拿到CSRF TOKEN

# 第二次請求:帶著初始cookie和TOKEN發送POST請求給登錄頁面,帶上賬號密碼
data={
    'commit':'Sign in',
    'utf8':'✓',
    'authenticity_token':authenticity_token,
    'login':'[email protected]',
    'password':'password'
}


# 測試一:沒有指定allow_redirects=False,則響應頭中出現Location就跳轉到新頁面,
# r2代表新頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie
             )

print(r2.status_code) # 200
print(r2.url) # 看到的是跳轉後的頁面
print(r2.history) # 看到的是跳轉前的response
print(r2.history[0].text) # 看到的是跳轉前的response.text

# 測試二:指定allow_redirects=False,則響應頭中即便出現Location也不會跳轉到新頁面,
# r2代表的仍然是老頁面的response
r2=requests.post('https://github.com/session',
             data=data,
             cookies=r1_cookie,
             allow_redirects=False
             )

print(r2.status_code) # 302
print(r2.url) # 看到的是跳轉前的頁面https://github.com/session
print(r2.history) # []

2.1.4 proxies

同添加headers方法一樣,代理參數是dict。

import requests
import re
def get_html(url):
    proxy = {
        'http': '120.25.253.234:812',
        'https' '163.125.222.244:8123'
    }
    heads = {}
    heads['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
    req = requests.get(url, headers=heads,proxies=proxy)
    html = req.text
    return html
def get_ipport(html):
    regex = r'<td data-title="IP">(.+)</td>'
    iplist = re.findall(regex, html)
    regex2 = '<td data-title="PORT">(.+)</td>'
    portlist = re.findall(regex2, html)
    regex3 = r'<td data-title="類型">(.+)</td>'
    typelist = re.findall(regex3, html)
    sumray = []
    for i in iplist:
        for p in portlist:
            for t in typelist:
                pass
            pass
        a = t+','+i + ':' + p
        sumray.append(a)
    print('代理')
    print(sumray)
if __name__ == '__main__':
    url = 'http://www.baidu.com'
    get_ipport(get_html(url))

某些介面增加了防騷擾模式,對於大規模且頻繁的請求,可能會彈出驗證碼,或者跳轉到登錄驗證頁面,或者封禁IP地址,此時如果想要正常訪問,可以通過設置代理來解決這個問題。
除了基本的HTTP代理外,requests還支持SOCKS協議的代理。

# 安裝socks庫
pip3 install "requests[socks]"

# 進行代理
import requests

proxies = {
    'http': 'socks5://user:password@host:port',
    'https': 'socks5://user:password@host:port'
}
res = requests.get('http://www.baidu.com', proxies=proxies)
print(res.status)  # 200

2.1.5 hooks

即鉤子方法,requests庫只支持一個response的鉤子,即在響應返回時,可以捎帶執行自定義方法。可以用於列印一些信息、做一些響應檢查、或者向響應中添加額外的信息。

import requests
url = 'http://www.baidu.com'

def verify_res(res, *args, **kwargs):
    print('url', res.url)
    res.status='PASS' if res.status_code == 200 else 'FAIL'

res = requests.get(url, hooks={'response': verify_res})
print(res.text) # <!DOCTYPE html><!--STATUS OK--><html> 
print(res.status) # PASS

2.1.6 stream

獲取內容立即下載開關,response會將報文一次性全部載入到記憶體中,如果報文過大,可以使用此參數,迭代下載。

import requests

url="http://www.baidu.com"

r = requests.get(url, stream=True)

# 解析response_body,以\n分割
for lines in r.iter_lines():
    print("lines:", lines)

# 解析response_body,以位元組分割
for chunk in r.iter_content(chunk_size=1024):
    print("chunk:", chunk)

2.1.7 verify

認證SSL證書開關,當發送HTTPS請求的時候,如果該網站的證書沒有被CA機構信任,程式將報錯,可以使用verify參數控制是否檢查SSL證書。

# 1、直接設置
import requests

response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)

# 2、請求時雖然設置了跳過檢查,但是程式運行時仍然會產生警告,警告中包含建議給我們的指定證書
# 可以通過設置,忽略屏蔽這個警告
from requests.packages import urllib3  # 如果報錯,則直接引入import urllib3

# 3、屏蔽警告
urllib3.disable_warnings()

response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code) # 200

# 4、通過cert直接聲明證書
# 本地需要有crt和key文件(key必須是解密狀態,加密狀態的key是不支持的),並指定它們的路徑,
response = requests.get('https://www.12306.cn',cert('/path/server.crt','/path/key'))
print(response.status_code) # 200

2.2 requests庫的異常

如何判斷是否出現異常呢?

2.2.1 raise_for_status()

該方法在內部判斷res.status_code是否等於200,不是則產生異常HTTPError

示例:

# 1、HTTPError異常示例
import requests
from requests.exceptions import HTTPError

try:
    res = requests.post("http://127.0.0.1:8080/example/post")
    res.raise_for_status()
    # 等同於
    if res.status != 200:
        raise HTTPError

    return res

except HTTPError:
    return False

2.2.2 ReadTimeout

該異常類型,將會捕捉到因請求/響應超時的請求。

# Timeout超時異常
import requests
from requests.exceptions import ReadTimeout

try:
    res = requests.get('http://127.0.0.1:8080/example/post',timeout=0.5)
    print(res.status_code)
    return res

except ReadTimeout:
    print('timeout')

2.2.3 RequestException

該異常類型,將會捕捉到因無請求引起的異常請求。

# RquestError異常
import requests
from requests.exceptions import RequestException

try:
    res = requests.get('http://127.0.0.1:8080/example/post')
    print(res.status_code)
    return res

except RequestException:
    print('reqerror')

3 總結

看到這裡,大家應該明白了,requests庫是一個比urilib2模塊更加簡潔的第三方庫,它具有如下的特點:

  • 支持HTTP連接保持和連接池
  • 支持使用cookie、session保持會話
  • 支持文件上傳
  • 支持自動響應內容的編碼
  • 支持國際化的URL和Post數據自動編碼
  • 支持自動實現持久連接keep-alive

因此,requests這個高度封裝的模塊,可以使我們的HTTP請求,變得更加人性化,使用它將可以輕而易舉的完成瀏覽器請求的任何操作,充分詮釋了它的口號:“HTTP for Humans”。

作者:京東物流 駱銅磊

來源:京東雲開發者社區


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • EBT3002串口伺服器晶元簡介 EBT3002 乙太網晶元是實現8路TTL串口數據與乙太網數據互相轉換的乙太網串口伺服器晶元;該乙太網晶元具有多種Modbus網關模式以及TCP/DUP/MQTT/HTTP物聯網網關模式,可滿足各類串口IO聯網設備與PLC設備的聯網功能。乙太網晶元採用採用LQFP1 ...
  • 確保密碼的安全性是非常重要的,以下是幾種常見的方法來提高密碼的安全性: 1. 使用加密傳輸:在密碼提交到後端之前,確保使用安全的加密協議(如HTTPS)來加密數據傳輸,以防止密碼被中間人攻擊竊取。 2. 密碼哈希:在後端接收到密碼後,使用密碼哈希演算法(如SHA-256)對密碼進行哈希處理,將密碼轉換 ...
  • 某日二師兄參加XXX科技公司的C++工程師開發崗位第16面: > 面試官:什麼是左值,什麼是右值? > > 二師兄:簡單來說,左值就是可以使用`&`符號取地址的值,而右值一般不可以使用`&`符號取地址。 ```c++ int a = 42; //a是左值,可以&a int* p = &a; int* ...
  • ## 一、初衷: 因為想要進行各種技術點的訓練和學習,開發中需要使用各種各樣的開源技術框架,苦於沒有基礎服務支撐,所以想要建立一個專門的服務支撐系統,每年購買的雲伺服器配置底下,安裝一個Jenkins都跑不起來,所以自己購買了一個物理主機,記憶體加裝到`32G`,搭建自己的私人技術知識星球。 搭建一套 ...
  • - 方法和函數的作用幾乎是一樣的,但是函數在使用的過程中更加靈活和多樣化 - scala中函數是頭等公民 . 可以作為方法的返回值和參數使用 - scala是一個集面向對象和麵向函數於一身的編程語言 , 靈活的函數是函數式編程的一種體現 - 函數的使用使代碼更加簡潔和靈活 # 函數 scala中一種 ...
  • > 最近項目中使用到了 lua,因為之前沒怎麼接觸過,特此記錄下自己在學習過程中疑惑的地方。 在使用`lua` 進行編碼的過程中,我們經常會使用到`.`和`:`,但是對於剛開始接觸`lua`的我來說,對這兩者的使用還是感到時常感到疑惑,接下來我們一起看看幾個例子,來感受兩者的區別。如果發現文中錯誤的 ...
  • # Go Redis 管道和事務之 go-redis ## [Go Redis 管道和事務官方文檔介紹](https://redis.uptrace.dev/zh/guide/go-redis-pipelines.html) Redis pipelines(管道) 允許一次性發送多個命令來提高性能, ...
  • 本篇博客的內容為RabbitMQ在開發過程中的快速上手使用,側重於代碼部分,幾乎沒有相關概念的介紹,相關概念請參考以下csdn博客,兩篇都是我找的精華帖,供大家學習。本篇博客也持續更新~~~ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...