返回 Social Auto Upload
get_baijiahao_cookie_headless.py
根目录 / examples / get_baijiahao_cookie_headless.py
1 # -*- coding: utf-8 -*-
2 """百家号(headless)扫码登录 → 保存 cookie。
3
4 说明:
5 - 无头浏览器打开百家号登录页并提取登录二维码,放大截图后保存为 png,
6 并用终端 ASCII 二维码展示;你手机/百度APP扫码登录。
7 - 扫码成功后自动把登录态写入 cookies/baijiahao_uploader/account.json。
8
9 用法:
10 python examples/get_baijiahao_cookie_headless.py
11 """
12 from pathlib import Path
13
14 from playwright.async_api import async_playwright
15 from conf import BASE_DIR
16 from utils.login_qrcode import (
17 build_login_qrcode_path,
18 print_terminal_qrcode,
19 )
20 from uploader.baijiahao_uploader.main import cookie_auth, baijiahao_logger
21
22
23 QR_SELECTOR = 'img[src^="https://passport.baidu.com/v2/api/qrcode"]'
24 LOGIN_BTN_TEXT = "登录"
25 LOGIN_URL = "https://baijiahao.baidu.com/builder/theme/bjh/login"
26
27
28 async def _grab_qr(page, qrcode_path: Path) -> str:
29 qr = page.locator(QR_SELECTOR).first
30 await qr.wait_for(state="attached", timeout=60000)
31 src = await qr.get_attribute("src")
32 if src and src.startswith("https://"):
33 resp = await page.context.request.get(src)
34 qrcode_path.parent.mkdir(parents=True, exist_ok=True)
35 qrcode_path.write_bytes(await resp.body())
36 else:
37 await qr.screenshot(path=str(qrcode_path))
38
39 qrcode_content = ""
40 try:
41 import cv2
42 img = cv2.imread(str(qrcode_path))
43 if img is not None:
44 h, w = img.shape[:2]
45 up = cv2.resize(img, (w * 3, h * 3), interpolation=cv2.INTER_CUBIC)
46 qrcode_content = cv2.QRCodeDetector().detectAndDecode(up)[0] or ""
47 except Exception:
48 pass
49 return qrcode_content or ""
50
51
52 async def _wait_login(page, max_checks: int = 120, interval: int = 3) -> bool:
53 import asyncio
54 async def _logged_in():
55 if "login" in page.url:
56 return False
57 ctx = page.context
58 cookies = await ctx.cookies()
59 if any(c.get("name") in ("BDUSS", "STOKEN") for c in cookies):
60 return True
61 return False
62
63 for _ in range(max_checks):
64 if await _logged_in():
65 return True
66 await asyncio.sleep(interval)
67 return False
68
69
70 async def main():
71 account_file = Path(BASE_DIR / "cookies" / "baijiahao_uploader" / "account.json")
72 account_file.parent.mkdir(parents=True, exist_ok=True)
73
74 import os
75 if os.path.exists(account_file) and await cookie_auth(str(account_file)):
76 baijiahao_logger.success("[+] cookie 已有效,无需重新登录")
77 return
78
79 qrcode_path = build_login_qrcode_path(str(account_file))
80 async with async_playwright() as playwright:
81 browser = await playwright.chromium.launch(
82 headless=True, args=["--no-sandbox", "--disable-blink-features=AutomationControlled"]
83 )
84 context = await browser.new_context()
85 page = await context.new_page()
86 await page.goto(LOGIN_URL, timeout=60000, wait_until="domcontentloaded")
87 await page.wait_for_timeout(4000)
88 # 进入登录弹窗
89 await page.get_by_text(LOGIN_BTN_TEXT, exact=True).first.click(timeout=10000)
90 await page.wait_for_timeout(4000)
91
92 qrcode_content = await _grab_qr(page, qrcode_path)
93 baijiahao_logger.info(f"🖼️ 二维码已保存: {qrcode_path}")
94 if qrcode_content:
95 print_terminal_qrcode(qrcode_content, qrcode_path, "百度APP/手机百度")
96 else:
97 print(f"未能解码二维码,请直接打开文件扫码:\n {qrcode_path}")
98
99 if await _wait_login(page):
100 baijiahao_logger.success("[+] 扫码登录成功,正在保存 cookie...")
101 await context.storage_state(path=str(account_file))
102 baijiahao_logger.success(f"[+] cookie 已保存: {account_file}")
103 else:
104 baijiahao_logger.error("[-] 等待扫码超时(约 6 分钟),未完成登录。")
105 await browser.close()
106
107
108 if __name__ == "__main__":
109 import asyncio
110
111 asyncio.run(main())
111 lines PYTHON