Fix Windows browser discovery, headless UA, and zh cookie banner

Local probes showed resolve_browser_path=None on Windows, HeadlessChrome
hard-blocked by Cloudflare, and cookie text「接受所有 Cookie」unmatched.
Also add scripts/local_turnstile_probe.py for 3-step smoke checks.
This commit is contained in:
chaos committed 2026-07-12 01:04:13 +08:00
1 parent 62b6ea8ea2
commit 3a0a76bf46
2 files changed
+473 -3

No files matched your search

+59 -3
View File
@@ -778,17 +778,59 @@ def apply_headless_to_options(options, headless: bool = True) -> None:
# - Google Chrome blocks unpacked extensions; CDP stealth alone often fails CF on servers
# - config browser_prefer: auto | chromium | chrome
# - config browser_path: absolute override
def _windows_browser_candidates() -> tuple[str, ...]:
"""Windows Chrome/Chromium paths (Program Files + common Playwright installs)."""
if sys.platform != "win32":
return ()
out: list[str] = []
local = os.environ.get("LOCALAPPDATA") or ""
pf = os.environ.get("PROGRAMFILES") or r"C:\Program Files"
pf86 = os.environ.get("PROGRAMFILES(X86)") or r"C:\Program Files (x86)"
# Prefer Chromium-like (can load unpacked extensions) over Google Chrome
if local:
# ms-playwright chromium-* / chrome-win64
try:
pw = os.path.join(local, "ms-playwright")
if os.path.isdir(pw):
for name in sorted(os.listdir(pw), reverse=True):
if not name.lower().startswith("chromium"):
continue
cand = os.path.join(pw, name, "chrome-win64", "chrome.exe")
if os.path.isfile(cand):
out.append(cand)
except Exception:
pass
out.append(os.path.join(local, "Chromium", "Application", "chrome.exe"))
out.append(os.path.join(local, "Google", "Chrome", "Application", "chrome.exe"))
out.append(os.path.join(pf, "Chromium", "Application", "chrome.exe"))
out.append(os.path.join(pf, "Google", "Chrome", "Application", "chrome.exe"))
out.append(os.path.join(pf86, "Google", "Chrome", "Application", "chrome.exe"))
# dedupe preserve order
seen: set[str] = set()
uniq: list[str] = []
for p in out:
key = p.lower()
if key in seen:
continue
seen.add(key)
uniq.append(p)
return tuple(uniq)
_WIN_BROWSERS = _windows_browser_candidates()
# Chromium first (turnstilePatch / --load-extension). On Windows, Playwright
# chromium-* paths contain "chromium" and pass _is_google_chrome_path=False.
CHROMIUM_CANDIDATES = (
"/usr/bin/chromium",
"/usr/bin/chromium-browser",
"/usr/lib/chromium/chromium",
"/usr/lib/chromium-browser/chromium-browser",
"/snap/bin/chromium", # keep as /snap/bin/chromium — do NOT resolve to /usr/bin/snap
)
) + tuple(p for p in _WIN_BROWSERS if "google" not in p.lower() or "chromium" in p.lower())
CHROME_CANDIDATES = (
"/usr/bin/google-chrome-stable",
"/usr/bin/google-chrome",
)
) + tuple(p for p in _WIN_BROWSERS if "google" in p.lower() and "chromium" not in p.lower())
# Legacy flat list (tests / external callers)
BROWSER_CANDIDATES = CHROMIUM_CANDIDATES + CHROME_CANDIDATES
@@ -1025,6 +1067,18 @@ def create_browser_options(headless=None):
options.set_pref("credentials_enable_service", False)
except Exception:
pass
# Force normal Chrome UA — default headless UA contains "HeadlessChrome"
# which Cloudflare often hard-blocks (Attention Required / blocked page).
ua = (get_user_agent() or "").strip()
if ua:
try:
options.set_user_agent(ua)
except Exception:
try:
options.set_argument(f"--user-agent={ua}")
except Exception:
pass
print(f" [browser] user-agent={ua[:72]}...", flush=True)
browser_path = resolve_browser_path()
if browser_path:
try:
@@ -3244,7 +3298,9 @@ function isVisible(node) {
const texts = [
'accept all cookies', 'accept all', 'reject all', 'allow all',
'accept cookies', 'got it', 'i agree', 'agree',
'接受全部', '全部接受', '拒绝全部', '全部拒绝', '同意'
// zh: UI shows "接受所有 Cookie" / "全部拒绝" (not only 接受全部)
'接受所有 cookie', '接受所有', '接受全部', '全部接受',
'拒绝全部', '全部拒绝', '同意'
];
const nodes = Array.from(document.querySelectorAll(
'button, a, [role="button"], [data-testid*="cookie"], [id*="cookie"], [class*="cookie"]'