--- name: dynamic-page-extract description: 提取SPA/动态渲染页面的完整内容,解决browser_snapshot无法获取JS渲染后DOM的问题 tags: [browser, spa, dynamic, scrape, cdp] --- # Dynamic Page Content Extraction `browser_snapshot` 获取的是 accessibility tree,JS 动态渲染的内容经常缺失。用 `browser_console` + CDP 绕过。 ## 核心方法:browser_console(expression=...) ```python # 获取完整页面文本 result = browser_console(expression="document.body ? document.body.innerText : 'no body'") # 获取特定元素内容 result = browser_console(expression="document.querySelector('.content')?.innerText") # 获取所有可见文本(排除script/style) result = browser_console(expression=""" Array.from(document.querySelectorAll('p, h1, h2, h3, h4, h5, h6, li, td, th, span, div')) .filter(el => el.offsetParent !== null && el.innerText.trim()) .map(el => el.innerText.trim()) .join('\\n') """) # 获取表格数据 result = browser_console(expression=""" JSON.stringify( Array.from(document.querySelectorAll('table tr')).map(row => Array.from(row.querySelectorAll('td, th')).map(cell => cell.innerText.trim()) ) ) """) ``` ## 等待动态内容 ```python # 等待特定内容出现 for _ in range(20): # 10秒超时 result = browser_console(expression=""" (function() { const el = document.querySelector('.result-content'); return el && el.innerText.trim() ? el.innerText.trim() : 'WAITING'; })() """) if 'WAITING' not in str(result): break terminal("sleep 0.5") ``` ## CDP Runtime.evaluate 获取完整 DOM ```python # 获取完整innerHTML(需设置 allow_unsafe_evaluate: true 或通过 browser_console) result = browser_console(expression="document.documentElement.outerHTML.substring(0, 50000)") # 获取body内HTML result = browser_console(expression="document.body.innerHTML.substring(0, 30000)") ``` ## 绕过限制 `browser_console(expression=...)` 在 sandbox 中可能被拦截 fetch/network。使用纯 DOM 读取: ```python # ✅ 允许 - DOM读取 browser_console(expression="document.querySelector('.price').innerText") # ❌ 可能被拦截 - 网络请求 browser_console(expression="fetch('/api/data')...") ``` 如需网络请求,用 `terminal` + curl 替代。 ## 交互操作:查找并点击隐藏/不可见按钮 `browser_snapshot` 只能看到 accessibility tree 中的元素,bricks 表单的 Submit 按钮经常不在 snapshot ref 中。用 `browser_console` IIFE 查找并点击: ```python # 查找 Submit 按钮(bricks 登录表单常见模式) browser_console(expression=""" (function(){ var all = document.querySelectorAll('*'); for(var i=0;i div, [class*=htoolbar] > div'); for(var i=0;i