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:
1 parent
62b6ea8ea2
commit
3a0a76bf46
2 files changed
+473
-3
No files matched your search
+59
-3
@@ -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"]'
|
||||
|
||||
Reference in new issue
Block a user