requests无法获取JS渲染内容,因其只请求原始HTML且不执行JavaScript;页面依赖fetch、axios或Vue/React动态加载数据,导致BeautifulSoup解析为空或仅得骨架代码。

为什么 requests + BeautifulSoup 抓不到 JS 渲染后的内容
因为 requests 只拿原始 HTML,不执行 JS;页面靠 fetch、axios 或 Vue/React 初始化数据,DOM 是空的或只有骨架。你看到的列表、分页、按钮点击后的结果,requests 一概看不见。
常见错误现象:BeautifulSoup.select(".item") 返回空列表;抓到的 div#content 里是 <!-- loading -->;翻页 URL 不变但内容刷新了——这些全是 JS 渲染的信号。
- 先用浏览器开发者工具(Network → XHR/Fetch)看真实数据接口,能直连就别上 Selenium
- 如果接口加密、带签名、依赖 Cookie 或 localStorage,或者页面逻辑复杂(如滑动加载、验证码交互),才必须走浏览器自动化
- 别在没确认 JS 是否必要时直接上
Selenium,它慢、重、CI 环境易崩
ChromeDriver + selenium.webdriver.Chrome 最小可用配置
不是装了 selenium 就能跑,版本错配是头号失败原因:Chrome 浏览器版本和 chromedriver 必须严格对应,差一个小版本都可能报 session not created。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 查 Chrome 版本:
chrome --version;去 chromedriver.chromium.org 下载同版本驱动 - 启动时加
--headless=new(新版 headless 模式)和--no-sandbox(尤其 Docker 或 Linux 服务端) - 禁用图片和 CSS 能提速:
options.add_argument("--blink-settings=imagesEnabled=false") - 务必设
options.add_experimental_option("excludeSwitches", ["enable-automation"]),否则某些网站会检测到自动化并拦截
等待 JS 渲染完成不能只靠 time.sleep()
time.sleep(3) 看似简单,实际极不可靠:网络快时浪费时间,慢时又等不够,还掩盖真实问题。Selenium 提供的显式等待才是正解,核心是等「某个元素出现」或「某个条件成立」。
常用等待场景:
- 等某个 class 的列表项渲染出来:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "product-item"))) - 等 AJAX 请求结束(检查
window.jQuery.active === 0或document.readyState === "complete") - 等某个按钮可点击(不只是存在):
EC.element_to_be_clickable((By.ID, "load-more")) - 避免用
presence_of_all_elements_located等全部加载完——有些页面懒加载无限滚动,永远等不完
提取数据前必须确认当前 DOM 是 JS 渲染后的最终态
很多人调用 driver.page_source 或 driver.find_element 后发现还是旧内容,其实是没等对时机,或者元素被包裹在 Shadow DOM / iframe 里。
关键检查点:
- 手动在浏览器里按 Ctrl+U 看源码,再按 F12 切到 Elements 面板,对比两者是否一致;不一致说明 JS 修改了 DOM,必须等渲染后再取
- 遇到
iframe,得先driver.switch_to.frame("name-or-id"),否则找不到里面的内容 - 遇到 Web Components(比如
<my-list>),可能需用shadow_root访问:elem.shadow_root.find_element(By.CSS_SELECTOR, ".item")(仅 Chromium 111+ 支持) - 动态生成的属性(如
data-loaded="true")比 class 更可靠,优先用它做等待或判断依据
JS 渲染的不确定性,本质是时间 + 上下文双重依赖;漏掉一个等待或切错上下文,拿到的就是半成品 DOM。










