requests无法获取JS渲染内容,因只下载原始HTML;Selenium需配置无头模式、禁用自动化特征、版本匹配,并用显式等待替代sleep,还需注入脚本隐藏webdriver特征。

直接用 requests 抓不到数据?不是代码写错了,是页面根本没把内容塞进初始 HTML 里——JS 渲染的内容必须等浏览器执行完脚本才出现。Selenium 不是“万能替代品”,而是你确认必须模拟真实浏览行为后的合理选择。
为什么 requests + BeautifulSoup 一定失败
它只下载原始 HTML 字符串,不解析、不执行任何 <script></script> 标签里的逻辑。比如访问知乎话题页,requests.get() 返回的源码里只有 ,真实列表藏在 React 渲染后生成的 DOM 节点中。
- 常见错误现象:
BeautifulSoup(html, "lxml").find("div", class_="content-list")返回None,但浏览器开发者工具里明明能看到这个 class - 本质原因:DOM 节点由 JS 创建,
requests拿不到“渲染结果”,只拿到“模板” - 性能影响:绕过这一步直接上 Selenium,会显著拖慢爬取速度,尤其批量任务时
Selenium 启动 Chrome 的最小可靠配置
别一上来就写 driver = webdriver.Chrome() —— 缺少必要参数会导致启动失败、被识别为自动化流量、或无法加载 JS。
- 必须加
--headless=new(新版无头模式,旧版--headless已弃用) - 必须禁用自动化特征:
--disable-blink-features=AutomationControlled,否则navigator.webdriver仍为true - 建议加
--no-sandbox和--disable-dev-shm-usage,避免 Linux 容器环境崩溃 - ChromeDriver 版本必须和本地 Chrome 浏览器主版本号严格一致(如 Chrome 124 → 需 ChromeDriver 124.x)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
<p>options = Options()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)</p>
等待 JS 渲染完成,别用 time.sleep()
硬等 3 秒看似简单,实际极不可靠:网速快时浪费时间,慢时又拿不到数据。Selenium 提供的显式等待才是稳定解法。
创建 Flask + Vue.js 全栈项目,采用单端口架构、uv 依赖管理、结构化日志和生产级前端设计。当用户要求以下操作时触发:创建新的 Flask+Vue 项目、搭建 Web 应用、构建全栈 Python+Vue 应用、初始化 Flask Web 项目、设置单端口 Flask 前后端项目。触发词:新建项目、创建项目、搭建项目、Flask项目、Vue项目。
- 错误写法:
time.sleep(3); driver.find_element(By.CLASS_NAME, "item") - 正确思路:等某个关键元素“存在”或“可见”,或等某段 JS 执行完毕返回非空值
- 常用判断:
presence_of_element_located(节点已插入 DOM)、visibility_of_element_located(节点可见且尺寸 > 0) - 注意:
find_element默认只查当前 DOM 快照,若 JS 尚未插入目标节点,会直接抛NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By <p>wait = WebDriverWait(driver, 10) # 最长等 10 秒 wait.until(EC.presence_of_element_located((By.CLASS_NAME, "product-list")))</p>
绕不过去的反爬细节:隐藏 webdriver 特征
很多网站(如淘宝、微博)会检测 navigator.webdriver 或 chrome.runtime 等属性,Selenium 默认值就是它们的拦截依据。
- 仅靠命令行参数不够,需在启动后立即覆盖 JS 运行时属性
- 执行
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {...})注入初始化脚本 - 关键操作包括:删除
Object.defineProperty(navigator, 'webdriver', ...)、重写plugins和languages属性 - 不处理这些,
driver.get()可能直接跳转到验证码页或 403 页面
真正麻烦的从来不是“怎么让 Selenium 跑起来”,而是“怎么让它看起来不像 Selenium”。这点容易被忽略,但决定你能不能拿到第一页数据。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










