从代理 API 获取代理 URL Args: api_url: 代理 API 地址,响应应为代理 URL 字符串或含代理 URL 的 JSON api_key: API 密钥(可选) api_key_header: API 密钥请求头名称 result_field: 从 JSON 响应中提取代理 URL 的字段路径,支持点号分隔(如 "data.proxy"),留空则使用响应原文 Returns: 代理 URL 字符串(如 http://user:pass@host:port),失败返
(api_url: str, api_key: str = "", api_key_header: str = "X-API-Key", result_field: str = "")
| 11 | |
| 12 | |
| 13 | def fetch_dynamic_proxy(api_url: str, api_key: str = "", api_key_header: str = "X-API-Key", result_field: str = "") -> Optional[str]: |
| 14 | """ |
| 15 | 从代理 API 获取代理 URL |
| 16 | |
| 17 | Args: |
| 18 | api_url: 代理 API 地址,响应应为代理 URL 字符串或含代理 URL 的 JSON |
| 19 | api_key: API 密钥(可选) |
| 20 | api_key_header: API 密钥请求头名称 |
| 21 | result_field: 从 JSON 响应中提取代理 URL 的字段路径,支持点号分隔(如 "data.proxy"),留空则使用响应原文 |
| 22 | |
| 23 | Returns: |
| 24 | 代理 URL 字符串(如 http://user:pass@host:port),失败返回 None |
| 25 | """ |
| 26 | try: |
| 27 | from curl_cffi import requests as cffi_requests |
| 28 | |
| 29 | headers = {} |
| 30 | if api_key: |
| 31 | headers[api_key_header] = api_key |
| 32 | |
| 33 | response = cffi_requests.get( |
| 34 | api_url, |
| 35 | headers=headers, |
| 36 | timeout=10, |
| 37 | impersonate="chrome110" |
| 38 | ) |
| 39 | |
| 40 | if response.status_code != 200: |
| 41 | logger.warning(f"动态代理 API 返回错误状态码: {response.status_code}") |
| 42 | return None |
| 43 | |
| 44 | text = response.text.strip() |
| 45 | |
| 46 | # 尝试解析 JSON |
| 47 | if result_field or text.startswith("{") or text.startswith("["): |
| 48 | try: |
| 49 | import json |
| 50 | data = json.loads(text) |
| 51 | if result_field: |
| 52 | # 按点号路径逐层提取 |
| 53 | for key in result_field.split("."): |
| 54 | if isinstance(data, dict): |
| 55 | data = data.get(key) |
| 56 | elif isinstance(data, list) and key.isdigit(): |
| 57 | data = data[int(key)] |
| 58 | else: |
| 59 | data = None |
| 60 | if data is None: |
| 61 | break |
| 62 | proxy_url = str(data).strip() if data is not None else None |
| 63 | else: |
| 64 | # 无指定字段,尝试常见键名 |
| 65 | for key in ("proxy", "url", "proxy_url", "data", "ip"): |
| 66 | val = data.get(key) if isinstance(data, dict) else None |
| 67 | if val: |
| 68 | proxy_url = str(val).strip() |
| 69 | break |
| 70 | else: |