fix(twitter): 进主页后关 cookie 横幅 + 点掉「敏感内容」确认页
敏感内容账号的主页会挡一层 "Yes, view profile" 确认,不点就不加载 timeline,导致抓到 0 条。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -266,6 +266,8 @@ class XTwitterScraper:
|
||||
await page.goto(target, wait_until="domcontentloaded", timeout=45000)
|
||||
# 等首批 GraphQL 响应落地
|
||||
await self._wait_settle(page, 2.0)
|
||||
# 关 cookie 横幅 + 点掉「敏感内容」确认页(否则 timeline 不会加载)
|
||||
await self._dismiss_gates(page)
|
||||
|
||||
await self._scroll_loop(page, deadline)
|
||||
except ScrapeCancelled:
|
||||
@@ -320,6 +322,48 @@ class XTwitterScraper:
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
async def _dismiss_gates(self, page) -> None:
|
||||
"""关掉 cookie 同意横幅;点掉「此账号可能含敏感内容 → 是的,查看」确认页。"""
|
||||
# cookie 横幅:点「拒绝非必要」/「Accept all」任一即可消失
|
||||
for sel in (
|
||||
"button:has-text('Refuse non-essential cookies')",
|
||||
"button:has-text('拒绝非必要 Cookie')",
|
||||
"button:has-text('Accept all cookies')",
|
||||
"button:has-text('接受所有 Cookie')",
|
||||
):
|
||||
try:
|
||||
btn = page.locator(sel).first
|
||||
if await btn.count() and await btn.is_visible():
|
||||
await btn.click(timeout=3000)
|
||||
await asyncio.sleep(0.6)
|
||||
break
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
# 敏感内容确认:多试几次(账号 UI 语言可能是英文或中文)
|
||||
clicked = False
|
||||
for _ in range(3):
|
||||
for sel in (
|
||||
"button:has-text('Yes, view profile')",
|
||||
"button:has-text('是的,查看个人资料')",
|
||||
"button:has-text('是的,查看个人资料')",
|
||||
"[data-testid='empty_state_button_text']",
|
||||
"a[href='/settings/content_you_see'] ~ button",
|
||||
):
|
||||
try:
|
||||
btn = page.locator(sel).first
|
||||
if await btn.count() and await btn.is_visible():
|
||||
await btn.click(timeout=3000)
|
||||
clicked = True
|
||||
self.log("已点掉「敏感内容」确认页")
|
||||
break
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
if clicked:
|
||||
break
|
||||
await asyncio.sleep(1.0)
|
||||
if clicked:
|
||||
await self._wait_settle(page, 3.0)
|
||||
|
||||
async def _wait_settle(self, page, seconds: float) -> None:
|
||||
try:
|
||||
await page.wait_for_load_state("networkidle", timeout=int(seconds * 1000))
|
||||
|
||||
Reference in New Issue
Block a user