顺丰HTTP客户端
| 248 | |
| 249 | # ==================== HTTP客户端 ==================== |
| 250 | class SFHttpClient: |
| 251 | """顺丰HTTP客户端""" |
| 252 | |
| 253 | def __init__(self, config: Config, proxy_manager: ProxyManager): |
| 254 | self.config = config |
| 255 | self.proxy_manager = proxy_manager |
| 256 | self.session = requests.Session() |
| 257 | self.session.verify = False |
| 258 | |
| 259 | # 设置代理 |
| 260 | proxy = self.proxy_manager.get_proxy() |
| 261 | if proxy: |
| 262 | self.session.proxies = proxy |
| 263 | |
| 264 | # 默认请求头 |
| 265 | self.headers = { |
| 266 | 'Host': 'mcs-mimp-web.sf-express.com', |
| 267 | 'upgrade-insecure-requests': '1', |
| 268 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63090551) XWEB/6945 Flue', |
| 269 | 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', |
| 270 | 'sec-fetch-site': 'none', |
| 271 | 'sec-fetch-mode': 'navigate', |
| 272 | 'sec-fetch-user': '?1', |
| 273 | 'sec-fetch-dest': 'document', |
| 274 | 'accept-language': 'zh-CN,zh', |
| 275 | 'platform': 'MINI_PROGRAM', |
| 276 | } |
| 277 | |
| 278 | def _generate_sign(self) -> Dict[str, str]: |
| 279 | """生成API签名""" |
| 280 | timestamp = str(int(round(time.time() * 1000))) |
| 281 | data = f'token={self.config.TOKEN}×tamp={timestamp}&sysCode={self.config.SYS_CODE}' |
| 282 | signature = hashlib.md5(data.encode()).hexdigest() |
| 283 | |
| 284 | return { |
| 285 | 'sysCode': self.config.SYS_CODE, |
| 286 | 'timestamp': timestamp, |
| 287 | 'signature': signature |
| 288 | } |
| 289 | |
| 290 | def request( |
| 291 | self, |
| 292 | url: str, |
| 293 | method: str = 'POST', |
| 294 | data: Optional[Dict] = None, |
| 295 | max_retries: int = REQUEST_RETRY_COUNT |
| 296 | ) -> Optional[Dict[str, Any]]: |
| 297 | """发送HTTP请求,带双层重试机制 |
| 298 | |
| 299 | Args: |
| 300 | url: 请求URL |
| 301 | method: 请求方法 GET/POST |
| 302 | data: 请求数据 |
| 303 | max_retries: 最大重试次数 |
| 304 | |
| 305 | Returns: |
| 306 | 响应JSON数据或None |
| 307 | """ |