Python 的 requests 和 httpx 模組簡化了 HTTP 請求的流程,提供更便捷的網路互動方式。requests 以其簡潔易用的 API 受到廣泛應用,而 httpx 則支援非同步請求,能有效提升應用程式效能。除了基本的 GET、POST 請求,理解錯誤處理和驗證機制也至關重要。此外,整合 Tor 網路能進一步提升網路隱私和安全性,stem 模組則提供了控制 Tor 的介面,讓開發者能更精細地管理 Tor 連線。結合這些工具和技術,能更有效地建構網路應用程式,滿足不同場景下的需求。
使用requests模組進行HTTP程式設計
簡介
本章節將介紹如何使用Python的requests模組進行HTTP程式設計,包括GET、POST等請求方法的使用,以及如何處理回應和錯誤。
使用httpbin.org測試REST請求
httpbin.org提供了一個測試REST請求的服務,支援GET、POST、PATCH、PUT和DELETE等方法。我們可以透過傳送請求到httpbin.org的特定端點來測試我們的HTTP客戶端。
GET請求範例
當我們向http://httpbin.org/get傳送GET請求時,我們會收到一個JSON格式的回應:
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "es-ES,es;q=0.9",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-5edd6c96-6e68236005a1c6a2aadef888"
},
"origin": "84.127.93.2",
"url": "http://httpbin.org/get"
}
GET請求程式碼範例
import requests
response = requests.get("http://httpbin.org/get", timeout=5)
print("HTTP 狀態碼:", response.status_code)
print(response.headers)
if response.status_code == 200:
results = response.json()
for result in results.items():
print(result)
print("回應標頭:")
for header, value in response.headers.items():
print(header, '-->', value)
print("請求標頭:")
for header, value in response.request.headers.items():
print(header, '-->', value)
print("伺服器:", response.headers['server'])
else:
print("錯誤碼 %s" % response.status_code)
內容解密:
- 傳送GET請求到http://httpbin.org/get,並設定超時時間為5秒。
- 輸出HTTP狀態碼和回應標頭。
- 如果狀態碼為200,則解析回應內容並輸出。
- 輸出回應標頭和請求標頭。
- 輸出伺服器資訊。
傳送POST請求
與GET方法不同,POST方法允許我們在請求主體中向伺服器傳送資料。
POST請求範例
import requests
import json
data_dictionary = {"id": "0123456789"}
headers = {"Content-Type": "application/json", "Accept": "application/json"}
response = requests.post("http://httpbin.org/post", data=data_dictionary, headers=headers, json=data_dictionary)
print("HTTP 狀態碼:", response.status_code)
print(response.headers)
if response.status_code == 200:
results = response.json()
for result in results.items():
print(result)
print("回應標頭:")
for header, value in response.headers.items():
print(header, '-->', value)
print("請求標頭:")
for header, value in response.request.headers.items():
print(header, '-->', value)
print("伺服器:", response.headers['server'])
else:
print("錯誤碼 %s" % response.status_code)
內容解密:
- 定義一個資料字典
data_dictionary,包含要傳送的資料。 - 定義請求標頭
headers,設定Content-Type為application/json。 - 傳送POST請求到http://httpbin.org/post,攜帶資料字典和請求標頭。
- 輸出HTTP狀態碼和回應標頭。
- 如果狀態碼為200,則解析回應內容並輸出。
使用代理伺服器
requests模組允許我們透過代理伺服器傳送請求。
代理伺服器設定範例
import requests
http_proxy = "http://<ip_address>:<port>"
proxy_dictionary = {"http": http_proxy}
response = requests.get("http://domain.com", proxies=proxy_dictionary)
內容解密:
- 定義代理伺服器的IP位址和埠號。
- 建立一個字典
proxy_dictionary,包含代理伺服器的設定。 - 傳送GET請求到指定網址,攜帶代理伺服器設定。
使用 requests 和 httpx 建構 HTTP 客戶端
在 Python 中,使用 HTTP 請求與伺服器進行互動是一項常見任務。requests 和 httpx 是兩個流行的函式庫,分別提供同步和非同步的 HTTP 請求功能。
使用 requests 管理例外
requests 模組以不同的方式處理錯誤。以下範例示範如何使用 requests 發起 GET 請求,並處理可能出現的錯誤:
import requests
try:
response = requests.get('http://www.google.com/pagenotexists')
response.raise_for_status()
except requests.exceptions.HTTPError as errh:
print(f"HTTP Error: {errh}")
except requests.exceptions.ConnectionError as errc:
print(f"Error Connecting: {errc}")
內容解密:
requests.get():發起 GET 請求。response.raise_for_status():如果請求傳回了不成功的狀態碼(4xx 或 5xx),則引發HTTPError。try-except區塊:捕捉並處理HTTPError和ConnectionError例外。
建構 HTTP 客戶端與 httpx
httpx 是一個支援非同步請求的 HTTP 客戶端,支援 HTTP/1.1 和 HTTP/2 協定。首先,使用 pip 安裝 httpx:
pip3 install httpx
基本使用範例
import httpx
client = httpx.Client(timeout=10.0)
response = client.get("http://www.google.es")
print(response.status_code)
print(response.text)
內容解密:
httpx.Client(timeout=10.0):建立一個超時為 10 秒的 HTTP 客戶端。client.get():發起 GET 請求。response.status_code和response.text:取得請求的狀態碼和回應內容。
使用 httpx 進行非同步請求
httpx 支援非同步請求,可與 asyncio 或 trio 等非同步框架結合使用。以下範例示範如何使用 asyncio 發起非同步 GET 請求:
import httpx
import asyncio
async def request_http1():
async with httpx.AsyncClient() as client:
response = await client.get("http://www.google.es")
print(response.http_version)
asyncio.run(request_http1())
內容解密:
httpx.AsyncClient():建立一個非同步 HTTP 客戶端。await client.get():非同步發起 GET 請求。asyncio.run():執行非同步函式。
啟用 HTTP/2 支援
預設情況下,httpx 不啟用 HTTP/2 支援。要啟用 HTTP/2,需要安裝 http2 擴充功能並設定 http2=True:
import httpx
import asyncio
async def request_http2():
async with httpx.AsyncClient(http2=True) as client:
response = await client.get("https://www.google.es")
print(response.http_version)
asyncio.run(request_http2())
內容解密:
http2=True:啟用 HTTP/2 支援。client.get():發起 GET 請求,並使用 HTTP/2 協定。
使用 trio 進行平行請求
trio 是一個友好的 Python 非同步平行函式庫。以下範例示範如何使用 trio 發起平行請求:
import httpx
import trio
async def fetch_result(client, url, results):
response = await client.get(url)
results[url] = response
async def main_parallel_requests():
async with httpx.AsyncClient(http2=True) as client:
async with trio.open_nursery() as nursery:
for i in range(2000, 2020):
url = f"https://en.wikipedia.org/wiki/{i}"
nursery.start_soon(fetch_result, client, url, results)
results = {}
trio.run(main_parallel_requests)
print(results)
內容解密:
trio.open_nursery():建立一個 nursery 以管理平行任務。nursery.start_soon():啟動一個平行任務來執行fetch_result函式。fetch_result:發起 GET 請求並將結果儲存在results字典中。
總之,httpx 提供了一個強大且靈活的 HTTP 客戶端,支援同步和非同步請求,並可與多種非同步框架結合使用。透過選擇合適的協定(如 HTTP/1.1 或 HTTP/2)和平行處理技術,可以有效地提高應用程式的效能和可擴充套件性。
HTTP驗證機制與Python實作
在現代網路服務中,大多數服務都需要驗證機制來確保使用者憑證的有效性。本章節將探討HTTP驗證機制的基礎知識及其在Python中的實作方式。
HTTP驗證機制簡介
HTTP協定原生支援三種驗證機制:
- HTTP基本驗證(Basic Authentication):使用Base64編碼使用者名稱和密碼,格式為
使用者名稱:密碼。 - HTTP摘要驗證(Digest Authentication):使用MD5加密使用者資訊、鍵值和realm雜湊。
- HTTP Bearer驗證:根據
access_token的驗證機制,例如OAuth協定。
Python的requests模組支援基本驗證和摘要驗證。兩者的主要區別在於,基本驗證僅進行編碼而不加密,而摘要驗證則使用MD5格式加密使用者資訊。
HTTP基本驗證實作
HTTP基本驗證是一種簡單的驗證機制,易於在Apache伺服器上實作。然而,其安全性較低,因為憑證以明文傳輸,容易被Wireshark等工具攔截。
#!/usr/bin/env python3
import requests
from requests.auth import HTTPBasicAuth
from getpass import getpass
username = input("Enter username: ")
password = getpass()
response = requests.get('https://api.github.com/user', auth=HTTPBasicAuth(username, password))
print('Response.status_code:' + str(response.status_code))
if response.status_code == 200:
print('Login successful :' + response.text)
內容解密:
- 使用
requests.get()方法傳送GET請求至GitHub API,並使用HTTPBasicAuth類別提供使用者憑證。 HTTPBasicAuth(username, password)將使用者名稱和密碼編碼後加入Authorization標頭。- 若登入成功,回傳狀態碼200,並顯示使用者資訊。
HTTP摘要驗證實作
HTTP摘要驗證使用MD5加密演算法來加密使用者資訊、鍵值和realm,提高了安全性。
#!/usr/bin/env python3
import requests
from requests.auth import HTTPDigestAuth
from getpass import getpass
user = input("Enter user: ")
password = getpass()
url = 'http://httpbin.org/digest-auth/auth/user/pass'
response = requests.get(url, auth=HTTPDigestAuth(user, password))
print("Headers request : ")
for header, value in response.request.headers.items():
print(header, '-->', value)
print('Response.status_code:' + str(response.status_code))
if response.status_code == 200:
print('Login successful :' + str(response.json()))
內容解密:
- 使用
HTTPDigestAuth類別進行摘要驗證,將使用者名稱和密碼加密後傳輸。 requests.get()方法傳送GET請求至指定的URL,並攜帶加密的驗證資訊。- 若登入成功,回傳狀態碼200,並顯示登入成功訊息及相關資料。
連線至Tor網路與探索隱藏服務
近年來,隱私已成為資訊科技安全的基本要素。Tor能夠幫助使用者實作網路匿名性,Tor是一個由全球志願者運作的電腦網路,為需要的人提供線上匿名服務。本章將首先介紹The Onion Router(Tor)專案如何幫助我們研究和開發工具,以確保使用者在網路瀏覽時的匿名性和隱私。Tor透過在構成Tor網路的各節點之間建立虛擬電路來實作這一點。
Tor的工作原理與匿名性
從匿名性的角度來看,Tor能夠防止網站追蹤使用者。藉助諸如requests、socks和stem等套件,Python簡化了搜尋和發現隱藏服務的過程。在本章中,我們將探討爬蟲方法,並展示Python生態系統中可用的資源,以完成這項任務。
使用Python與Tor網路互動
使用requests模組與Tor網路互動
首先,我們需要了解如何使用requests模組與Tor網路互動。為了實作這一點,我們需要設定代理伺服器,以下是具體的程式碼範例:
import requests
# 設定Tor代理
proxies = {
'http': 'socks5h://127.0.0.1:9050',
'https': 'socks5h://127.0.0.1:9050'
}
# 傳送請求
response = requests.get('http://example.com', proxies=proxies)
#### 內容解密:
# 在這段程式碼中,我們首先匯入了requests模組。
# 然後,我們定義了一個字典proxies,用於設定Tor代理。
# 'http'和'https'鍵對應的值是Tor代理的位址和埠。
# 最後,我們使用requests.get()方法發送了一個GET請求到指定的URL,並將proxies引數設為我們定義的代理字典。
print(response.text)
使用stem模組控制Tor
stem模組是另一個重要的工具,它允許我們控制Tor。以下是使用stem連線至Tor控制埠並取得電路資訊的範例:
from stem import Signal
from stem.control import Controller
# 連線至Tor控制埠
with Controller.from_port(port=9051) as controller:
controller.authenticate()
# 取得目前的電路
circuits = controller.get_circuits()
for circuit in circuits:
print(circuit.id)
#### 內容解密:
# 這段程式碼首先匯入了stem模組中的Signal和Controller類別。
# 然後,它使用Controller.from_port()方法連線至Tor控制埠,並進行身份驗證。
# authenticate()方法用於驗證控制器的身份。
# get_circuits()方法用於取得目前的Tor電路。
# 最後,它遍歷並列印出每個電路的ID。
# 請求新的身份
controller.signal(Signal.NEWNYM)
#### 內容解密:
# 這行程式碼請求Tor提供新的身份,這通常意味著重新建立電路以提高匿名性。
問題
- 如何使用
requests模組透過Tor代理傳送HTTP請求? stem模組的主要功能是什麼,如何用它來控制Tor?- 為什麼在某些應用程式中使用Tor是必要的?