根本原因是requests仅获取服务器返回的原始html字节流,不执行js、不加载iframe、不处理重定向;浏览器elements面板显示的是js渲染、ajax注入、iframe加载后的最终dom。

根本原因不是代码写错了,而是你拿到的压根就不是浏览器最终渲染出来的那个 DOM。
requests.get() 拿到的是原始 HTML 字节流,不是 Elements 面板里的 DOM
浏览器 Elements 面板显示的是 JS 执行、AJAX 注入、iframe 加载后的最终结构;requests.get() 只负责发一次 HTTP 请求,拿回服务器吐出的原始 HTML 字符串——它不执行 JS、不加载 iframe、不处理重定向、也不解析 <meta charset>。
- 右键网页 → “View Page Source”,搜索你要的内容:搜不到 → 基本确定是 JS 动态渲染
- 对比
response.text和浏览器 Preview 标签页(Network → 刷新 → 点 HTML 请求 → Preview):结构差异大 → 渲染介入了 - 禁用 JS 后刷新页面(DevTools → Settings → Debugger → “Disable JavaScript”):内容消失 → 强依赖 JS
常见干扰项:User-Agent、编码、重定向、iframe
即使没 JS 渲染,也可能因服务端策略导致内容不一致。
-
User-Agent是默认的python-requests/2.31.0?很多网站会返回简化版或缓存页,换成 Chrome 的 UA 头常能解决 - 中文乱码?别信
response.text,改用response.content.decode('utf-8', errors='replace')或chardet.detect()显式解码 -
response.url和你请求的 URL 不一样?说明发生了 302 重定向,但你没察觉;加allow_redirects=False检查状态码 - 目标内容在
<iframe src="xxx"></iframe>里?requests不会自动请求 iframe 地址,得单独抓那个srcURL
怎么确认是不是该换方案?看 Network 面板找 XHR/Fetch
如果内容确实是动态加载的,硬刚 requests + BeautifulSoup 效率低还容易崩。直接定位数据源头更稳。
- 刷新页面,切到 Network 面板,过滤
XHR或Fetch,找返回 JSON 或 HTML 片段的请求 - 点开它 → Response 标签页,看内容是否就是你要的数据;Preview 是否结构清晰
- 右键该请求 → “Copy → Copy as cURL”,再转成
requests代码(注意 headers 和参数) - 若返回 JSON,直接用
response.json()解析,比正则或 CSS 选择器可靠得多
Selenium 等工具不是万能解药,用错等待条件照样失败
很多人以为上了 Selenium 就万事大吉,结果 WebDriverWait 总超时——问题常出在等待逻辑本身。
-
presence_of_element_located只管元素是否插入 DOM,不管它是否可见、可点击、或文本是否填完 - 等按钮可点:用
element_to_be_clickable - 等某段文字出现(比如异步填充的
<span></span>):用text_to_be_present_in_element((By.XPATH, '//span'), '预期文本') - 等 loading 类消失:用
invisibility_of_element_located((By.CLASS_NAME, 'loading')) - 页面跳转或进了 iframe?必须重新指定上下文,比如
driver.switch_to.frame(),否则等待永远在旧 DOM 快照里查
最易被忽略的一点:所谓“一致”,其实是分层的。源码一致 ≠ 渲染后一致 ≠ 用户看到的一致。别一上来就怀疑 selector 写错,先确认你到底该在哪一层干活——是跟服务器要原始数据,还是跟浏览器要最终视图,这个判断错了,后面全白搭。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











