9e0644095f
移除 Playwright 浏览器自动化,改用 passport/SSO HTTP 接口获取二维码与轮询登录;后端模块化拆分,前端替换为 Vue3 SPA。 Co-authored-by: Cursor <cursoragent@cursor.com>
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
import json
|
||
import logging
|
||
import time
|
||
|
||
import requests
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def get_proxy_from_api(api_url, max_retries=3, timeout=10):
|
||
if not api_url:
|
||
return None
|
||
last_error = None
|
||
for attempt in range(max_retries):
|
||
try:
|
||
resp = requests.get(api_url, timeout=timeout)
|
||
resp.raise_for_status()
|
||
content = resp.text.strip()
|
||
if not content:
|
||
raise ValueError("代理 API 返回空内容")
|
||
try:
|
||
data = resp.json()
|
||
if "ip" in data and "port" in data:
|
||
proxy_str = f"{data['ip']}:{data['port']}"
|
||
else:
|
||
proxy_str = content
|
||
except json.JSONDecodeError:
|
||
proxy_str = content
|
||
if not proxy_str.startswith(("http://", "https://")):
|
||
proxy_str = f"http://{proxy_str}"
|
||
return {"server": proxy_str}
|
||
except Exception as e:
|
||
last_error = e
|
||
if attempt < max_retries - 1:
|
||
wait = 2 ** attempt
|
||
logger.warning("获取代理失败 (第%s次): %s,%ss 后重试", attempt + 1, e, wait)
|
||
time.sleep(wait)
|
||
logger.error("获取代理失败,已重试%s次: %s", max_retries, last_error)
|
||
return None
|
||
|
||
|
||
def test_proxy_api(proxy_api):
|
||
proxy = get_proxy_from_api(proxy_api, timeout=5)
|
||
if not proxy:
|
||
return {"status": "error", "message": "获取代理失败"}
|
||
proxies = {"http": proxy["server"], "https": proxy["server"]}
|
||
test_urls = [
|
||
"http://httpbin.org/ip",
|
||
"https://api.ipify.org?format=json",
|
||
]
|
||
last_err = None
|
||
for test_url in test_urls:
|
||
try:
|
||
resp = requests.get(test_url, proxies=proxies, timeout=10)
|
||
if resp.status_code == 200:
|
||
try:
|
||
data = resp.json()
|
||
ip = data.get("origin") or data.get("ip", "unknown")
|
||
except json.JSONDecodeError:
|
||
ip = resp.text.strip()[:64] or "unknown"
|
||
return {"status": "success", "ip": ip, "message": "代理可用"}
|
||
except Exception as e:
|
||
last_err = e
|
||
return {"status": "error", "message": f"代理测试失败: {last_err}"}
|