first commit

This commit is contained in:
2026-08-11 16:18:44 +08:00
commit 5cc322a598
231 changed files with 33294 additions and 0 deletions

65
fetcher.py Normal file
View File

@@ -0,0 +1,65 @@
"""带限速、重试、SSL 宽松回退的 HTTP 抓取。"""
import time
import requests
import urllib3
from config import MAX_RETRIES, REQUEST_DELAY, REQUEST_TIMEOUT, USER_AGENT
# 站点证书在部分环境下校验失败curl 需 -k先严格再回退宽松
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
_session = requests.Session()
_session.headers.update({"User-Agent": USER_AGENT})
_last_request_ts = 0.0
def _throttle() -> None:
"""简单限速:保证两次请求之间至少间隔 REQUEST_DELAY 秒。"""
global _last_request_ts
now = time.monotonic()
wait = REQUEST_DELAY - (now - _last_request_ts)
if wait > 0:
time.sleep(wait)
_last_request_ts = time.monotonic()
def _get(url: str, **kwargs) -> requests.Response:
"""GETSSL 校验失败时自动回退到不校验证书。"""
try:
return _session.get(url, timeout=REQUEST_TIMEOUT, verify=True, **kwargs)
except requests.exceptions.SSLError:
return _session.get(url, timeout=REQUEST_TIMEOUT, verify=False, **kwargs)
def fetch_text(url: str) -> str:
"""抓取并返回 UTF-8 文本,带重试。"""
last_err: Exception | None = None
for attempt in range(1, MAX_RETRIES + 1):
_throttle()
try:
resp = _get(url)
resp.raise_for_status()
resp.encoding = resp.apparent_encoding or "utf-8"
return resp.text
except requests.RequestException as e:
last_err = e
time.sleep(0.8 * attempt)
raise RuntimeError(f"抓取失败 {url}: {last_err}")
def fetch_bytes(url: str) -> bytes:
"""抓取二进制(图片等),带重试。"""
last_err: Exception | None = None
for attempt in range(1, MAX_RETRIES + 1):
_throttle()
try:
resp = _get(url)
resp.raise_for_status()
return resp.content
except requests.RequestException as e:
last_err = e
time.sleep(0.8 * attempt)
raise RuntimeError(f"抓取失败 {url}: {last_err}")