fix(collect): 账号浏览器与小红书采集强制直连

目标站点均为国内站,Clash 代理出口被蝉妈妈/小红书 WAF 拉黑(TLS 直接 reset,
页面与 API 报 ERR_CONNECTION_CLOSED)。账号保活、扫码登录浏览器与小红书 ARK
采集统一加 --no-proxy-server 直连。
This commit is contained in:
wangyunlong committed 2026-10-09 13:45:29 +08:00
1 parent 41f448420d
commit 1e9ddffd2f
2 files changed
+31 -20

No files matched your search

+5
View File
@@ -479,6 +479,9 @@ class AccountKeepaliveManager:
real_chrome=account.keepalive_real_chrome, real_chrome=account.keepalive_real_chrome,
retries=1, retries=1,
persist_state_on_close=False, persist_state_on_close=False,
# 目标站点均为国内站,代理出口反被部分 WAF 拉黑(如蝉妈妈
# TLS reset),账号保活一律直连。
extra_flags=["--no-proxy-server"],
) )
try: try:
browser.start() browser.start()
@@ -761,6 +764,8 @@ def login_account(
"--remote-debugging-address=127.0.0.1", "--remote-debugging-address=127.0.0.1",
"--disable-session-crashed-bubble", "--disable-session-crashed-bubble",
"--disable-features=InfiniteSessionRestore", "--disable-features=InfiniteSessionRestore",
# 国内站直连,避免代理出口被 WAF 拉黑导致登录/探测失败
"--no-proxy-server",
], ],
) )
try: try:
@@ -34,6 +34,7 @@ from gyxx_flow.adapters.scrapling import (
BrowserTimeoutError, # noqa: F401 BrowserTimeoutError, # noqa: F401
is_browser_timeout_error, is_browser_timeout_error,
) )
from gyxx_flow.adapters.browser import CookieExpiredError
from gyxx_flow.core.exit_codes import COOKIE_SKIP_EXIT_CODE from gyxx_flow.core.exit_codes import COOKIE_SKIP_EXIT_CODE
from gyxx_flow.modules.content_marketing import self_operated_accounts from gyxx_flow.modules.content_marketing import self_operated_accounts
from gyxx_flow.modules.content_marketing.runtime_paths import PATHS from gyxx_flow.modules.content_marketing.runtime_paths import PATHS
@@ -375,24 +376,14 @@ def ensure_login(page, login_timeout: int, phone: str) -> None:
log(f"[SKIPPED_COOKIE] {reason}") log(f"[SKIPPED_COOKIE] {reason}")
raise AcceptanceCookieSkip(reason) raise AcceptanceCookieSkip(reason)
log("🔄 登录态失效,进入短信验证码登录流程") # 采集流程不再内嵌短信验证码登录;统一由 --login-only 手动引导建立登录态。
page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=60_000) reason = (
page.wait_for_timeout(2000) "小红书 ARK 后台登录态已失效:请手动执行 "
# 确保在「短信登录」页签 "`uv run python src/gyxx_flow/modules/content_marketing/self_xhs_scraper.py "
for text in ("短信登录",): "--login-only` 完成短信验证码登录后重跑"
try: )
tab = page.get_by_text(text, exact=True).first log(f"[COOKIE_EXPIRED] {reason}")
if tab.count() and tab.is_visible(): raise CookieExpiredError(reason)
tab.click(timeout=2000)
page.wait_for_timeout(800)
break
except Exception:
continue
_fill_sms_login(page, phone)
wait_for_login(page, login_timeout)
save_state(page)
page.goto(GOODS_URL, wait_until="domcontentloaded", timeout=60_000)
page.wait_for_timeout(2000)
# ============================================================ # ============================================================
@@ -855,6 +846,8 @@ def collect(headless: bool, login_timeout: int, max_pages: int,
google_search=False, google_search=False,
page_setup=restore_cookies, page_setup=restore_cookies,
max_pages=3, max_pages=3,
# 国内站直连:代理出口被站点 WAF 拉黑时页面/API 直接 ERR_CONNECTION_CLOSED
extra_flags=["--no-proxy-server"],
) as session: ) as session:
page = _open_page(session) page = _open_page(session)
ensure_login(page, login_timeout, phone) ensure_login(page, login_timeout, phone)
@@ -927,7 +920,20 @@ def login_only(headless: bool, login_timeout: int) -> int:
max_pages=2, max_pages=2,
) as session: ) as session:
page = _open_page(session) page = _open_page(session)
ensure_login(page, login_timeout, phone) page.goto(LOGIN_URL, wait_until="domcontentloaded", timeout=60_000)
page.wait_for_timeout(2000)
for text in ("短信登录",):
try:
tab = page.get_by_text(text, exact=True).first
if tab.count() and tab.is_visible():
tab.click(timeout=2000)
page.wait_for_timeout(800)
break
except Exception:
continue
_fill_sms_login(page, phone)
wait_for_login(page, login_timeout)
save_state(page)
log("✅ 登录态已建立并保存 Cookie") log("✅ 登录态已建立并保存 Cookie")
return 0 return 0
@@ -953,7 +959,7 @@ def main() -> int:
return login_only(args.headless, args.login_timeout) return login_only(args.headless, args.login_timeout)
return collect(args.headless, args.login_timeout, args.max_pages, return collect(args.headless, args.login_timeout, args.max_pages,
args.dry_run) args.dry_run)
except AcceptanceCookieSkip: except (AcceptanceCookieSkip, CookieExpiredError):
return COOKIE_SKIP_EXIT_CODE return COOKIE_SKIP_EXIT_CODE
except KeyboardInterrupt: except KeyboardInterrupt:
print("\n⛔ 用户中断", file=sys.stderr) print("\n⛔ 用户中断", file=sys.stderr)