Python實現簡單封裝網絡請求的示例詳解
更新時間:2025年09月23日 15:40:08 作者:冰冷的bin
這篇文章主要為大家詳細介紹了Python實現簡單封裝網絡請求的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
安裝依賴
在開始使用前,需先安裝工具依賴的第三方庫。打開終端(命令行),執(zhí)行以下命令:
pip install requests tenacity
核心功能說明
1. 類與方法概覽
| 類/方法 | 功能描述 |
|---|---|
| ApiResponse 類 | 響應數據包裝類,提供狀態(tài)檢查、數據獲取等便捷方法 |
| NetHelper 類 | 核心請求封裝類,支持初始化配置、多 HTTP 方法調用 |
| get()/post()/put()/delete() | 對外暴露的快捷方法,分別對應 GET/POST/PUT/DELETE 請求 |
2.NetHelper類初始化參數
初始化 NetHelper 實例時,需傳入以下參數(均為可選,有默認值):
| 參數名 | 類型 | 說明 |
|---|---|---|
| base_url | str | 基礎 URL(如 https://api.example.com),請求路徑會自動拼接至此 URL |
| headers | Dict[str, str] | 默認請求頭(會被單次請求的頭覆蓋) |
| timeout | int | 請求超時時間(秒,默認 15 秒) |
| verify_ssl | bool | 是否驗證 SSL 證書(生產環(huán)境建議設為 True,測試環(huán)境可設為 False) |
3.ApiResponse類屬性與方法
ApiResponse 用于包裝接口響應數據,提供以下核心功能:
| 屬性/方法 | 類型 | 說明 |
|---|---|---|
| data | Any | 響應體解析后的數據(JSON 自動轉為字典,非 JSON 為文本/二進制) |
| status_code | int | HTTP 狀態(tài)碼(如 200、404) |
| error | Optional[str] | 錯誤信息(僅當狀態(tài)碼非 2xx 或發(fā)生異常時存在) |
| is_success() | bool | 檢查請求是否成功(狀態(tài)碼 2xx 且無錯誤信息時返回 True) |
使用實例
步驟 1:導入工具類
from net_helper import NetHelper, ApiResponse # 假設工具保存為 net_helper.py
步驟 2:初始化NetHelper實例
請求頭和基礎 URL 配置:
# 初始化 NetHelper
client = NetHelper(
base_url="https://com.text.com",
headers={
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json;charset=UTF-8",
},
)
步驟 3:發(fā)送登錄請求
使用 post() 方法發(fā)送 POST 請求,傳入請求體和參數:
response = client.post(
url="/login",
json={
"name": "bin",
"pwd": "123456",
}
)
步驟 4:處理響應結果
根據 ApiResponse 的屬性判斷請求是否成功,并獲取數據:
if response.is_success():
print("登錄成功!")
print("響應數據:", response.data)
print("狀態(tài)碼:", response.status_code)
else:
print(f"登錄失敗!錯誤信息: {response.error}")
print("狀態(tài)碼:", response.status_code)
print("原始響應:", response.data)
五、源碼
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import logging
import json as jsonlib
from typing import Dict, Optional, Union, Any
import requests
from tenacity import (
retry,
stop_after_attempt,
wait_exponential,
retry_if_exception_type,
)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
logger = logging.getLogger(__name__)
class ApiResponse:
"""API響應包裝類"""
def __init__(self, data: Any, status_code: int = 200, error: Optional[str] = None):
self.data = data
self.status_code = status_code
self.error = error
self.message = data.get('message', '') if isinstance(data, dict) else ''
def is_success(self) -> bool:
"""檢查請求是否成功"""
return 200 <= self.status_code < 300 and self.error is None
class NetHelper:
def __init__(self,
base_url: str,
headers: Optional[Dict[str, str]],
timeout: int = 15,
verify_ssl: bool = True):
self.base_url = base_url.rstrip("/")
self.default_headers = headers
self.timeout = timeout
self.verify_ssl = verify_ssl
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=10),
retry=retry_if_exception_type((
requests.exceptions.ConnectionError,
requests.exceptions.Timeout
)),
reraise=True
)
def _send_request(
self,
method: str = "GET",
url: str = "",
headers: Optional[Dict[str, str]] = None,
json: Optional[Union[Dict[str, Any], str]] = None,
data: Optional[Union[Dict[str, Any], str, bytes]] = None,
params: Optional[Dict[str, Any]] = None
) -> ApiResponse:
"""內部請求方法"""
# 拼接完整URL
full_url = f"{self.base_url}/{url.lstrip('/')}"
# 合并請求頭
merged_headers = {**self.default_headers, **(headers or {})}
# 移除空值頭
merged_headers = {k: v for k, v in merged_headers.items() if v is not None}
try:
# 打印請求體
print("請求方法:", method.upper())
print("請求URL:", full_url)
if params:
print("請求參數:")
print(jsonlib.dumps(params, ensure_ascii=False, indent=2))
if json:
print("請求JSON數據:")
print(jsonlib.dumps(json, ensure_ascii=False, indent=2))
if data:
print("請求表單數據:")
if isinstance(data, (dict, list)):
print(jsonlib.dumps(data, ensure_ascii=False, indent=2))
else:
print(data)
# 發(fā)送請求
response = requests.request(
method=method.upper(),
url=full_url,
headers=merged_headers,
json=json,
data=data,
params=params,
timeout=self.timeout,
verify=self.verify_ssl
)
# 解析響應
try:
result_data = response.json()
except ValueError:
result_data = response.text if response.encoding else response.content
print("響應數據:")
print(jsonlib.dumps(result_data, ensure_ascii=False, indent=2))
# 檢查HTTP狀態(tài)碼
if 200 <= response.status_code < 300:
return ApiResponse(result_data, response.status_code)
else:
error_msg = f"HTTP錯誤: 狀態(tài)碼 {response.status_code}"
logger.error(f"{error_msg}, 響應: {result_data}")
return ApiResponse(result_data, response.status_code, error_msg)
except requests.exceptions.ConnectionError as e:
logger.error(f"連接失敗: 無法連接到 {full_url}")
return ApiResponse({}, 0, str(e))
except requests.exceptions.Timeout as e:
logger.error(f"請求超時: 超過 {self.timeout} 秒")
return ApiResponse({}, 0, str(e))
except Exception as e:
logger.error(f"未知錯誤: {str(e)}")
return ApiResponse({}, 0, str(e))
def post(self, url: str, data: Optional[Any] = None, params: Optional[Dict[str, Any]] = None) -> ApiResponse:
return self._send_request(method="POST", url=url, json=data, params=params)
def get(self, url: str, params: Optional[Dict[str, Any]] = None) -> ApiResponse:
return self._send_request(method="GET", url=url, params=params)
def put(self, url: str, data: Optional[Any] = None, params: Optional[Dict[str, Any]] = None) -> ApiResponse:
return self._send_request(method="PUT", url=url, json=data, params=params)
def delete(self, url: str, params: Optional[Dict[str, Any]] = None) -> ApiResponse:
return self._send_request(method="DELETE", url=url, params=params)
到此這篇關于Python實現簡單封裝網絡請求的示例詳解的文章就介紹到這了,更多相關Python封裝網絡請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺談flask中的before_request與after_request
這篇文章主要介紹了淺談flask中的before_request與after_request,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下2018-01-01

