13.4 Web分析与爬虫——动态页面爬取示例¶
内容梗概¶
本节课解决 Ajax 动态渲染页面的爬取问题。老师先分析:含 Ajax 的页面,浏览器能自动运行 JS 补全内容,所以用户看到完整页面;但 requests 拿到的 HTML 是残缺的,BeautifulSoup 又不提供 JavaScript 运行环境,直接解析无济于事。随后引入 Web 自动化测试工具 Selenium(课上未念名字,称"这个工具"):Python 程序驱动 chromedriver,再驱动真实 Chrome 浏览器,从而获得 JS 渲染环境。课程演示了环境配置三要素(装库、装浏览器、下载对应版本 driver 并配环境变量),以及用 driver.get + find_elements_by_css_selector 抓取动态页面学生名单的完整过程。
知识点详解¶
为什么 requests 搞不定动态页面(约 00:00–01:55)¶
- 不涉及 Ajax 时,
requests直接拿到整个页面的完整 HTML(即 13.3 的情形)。 - 若网站部分内容由 JavaScript 通过 Ajax 生成:浏览器访问时会自动运行 JS 并把取回的内容补全,用户看到的是完整 HTML;但爬虫用
requests请求,服务器除了返回残缺 HTML 外还返回一堆 JS,后续还要发新请求。 - 把这样的 HTML 直接扔给
BeautifulSoup没用——BeautifulSoup 不提供 JavaScript 运行环境(至少旧版本没有)。因此需要一个能提供 **JavaScript 渲染环境**的新工具。
Selenium:Web 自动化测试工具(约 01:55–04:00,09:40–11:40)¶
- 网上搜到的最常见工具就是 Selenium(老师自称发音总错,放弃念名字)。
- 它本是做 **Web 测试**的工具:公司开发页面后要验证页面跳转逻辑是否按设计工作,人工点击很愚蠢,于是用程序自动化地点页面——由此产生了自动化的 Web 测试平台。
- 并非专为 Python 开发,Java、Python 等多种语言都可用。
- 驱动链条:Python 程序(.py)→ driver.exe → 浏览器(如 chrome.exe)。运行程序会自动弹出浏览器窗口访问页面,浏览器顶栏会提示"Chrome 正在受自动测试软件的控制"。
动态页面实测对比(约 04:00–09:15)¶
- 演示对象:上一节课的 Flask 动态渲染演示网站(老师把默认端口 5000 改了一下),页面只显示前 10~20 个学生 ID,其余靠**滚动页面**触发 Ajax 加载。
- 用 13.3 的爬虫机制面对它的 bug:只能抓到前 10 个;后面内容没有超链接(
a元素),也无法模拟下拉滚动条,直接"傻眼"。 - 实测:直接用
requests抓到的 HTML 里,列表的li项**全部不见了**。原因:这些li是 JS 通过data?page=1访问后端接口拿到 JSON 串、再由 JavaScript 写进页面的;requests和BeautifulSoup都不运行 JS,自然拿不到 → 抓取失败。
环境配置三要素(约 11:40–15:35)¶
pipenv install selenium安装库(课上为省时间没用虚拟环境,直接装的)。- 本地装有浏览器(Chrome / Firefox 均可),并**确认版本号**(演示机 Chrome 为 83.0)。
- 下载**与浏览器版本完全对应**的 driver(Chrome 83 就不能下 84 的 driver),选择对应平台(win32 等);把
chromedriver.exe放进已在环境变量 PATH 中的目录(老师放在专门的ctools-bin目录),使命令行能直接运行chromedriver.exe。
代码逻辑(约 11:15–12:10,16:25–17:50)¶
- 与 requests 思路类似,不再需要 requests 发 HTTP 请求:
- API 名字好理解;
close会把受控的 Chrome 直接关掉(老师为演示效果先把 close 注释掉,让窗口留着)。 - 运行效果:自动弹出 Chrome 窗口访问地址,因为本质就是真实浏览器,能完整渲染 Ajax 出来的
li,于是成功抓到全部内容——和用户真实看到的页面一模一样。
同类工具与本质(约 18:20–19:00)¶
- Selenium 不是唯一选择,还有 PhantomJS 等其他工具,课后可自行学习,选喜欢的即可。
- 原理一致:内置/驱动一个 JavaScript 执行环境,把 Ajax 渲染的内容渲染出来,再分析 HTML——本质上仍在分析 HTML 页面来获取内容。
示例与演示¶
- 对比演示:同一动态网站,先用
requests抓取展示残缺的 HTML(li全消失),再用 Selenium 驱动 Chrome 抓取,成功得到全部学生 ID。 - 环境配置演示:查看 Chrome 版本(关于 Chrome → 83.0)→ 下载对应版本 win32 的 chromedriver → 放入 PATH 中的
ctools-bin目录 → 命令行验证chromedriver.exe可直接运行。 - 运行演示:注意先
cd到dynamic目录(老师自己一开始忘切换目录报错);运行后自动弹出 Chrome 窗口,页面提示"正在受自动测试软件的控制",成功提取所有li内容;注释掉close可保留窗口观察。 - 课堂小状况:升级 Windows 后疑似虚拟机导致演示卡顿,老师提示卡住可看回放——无实质知识内容。
重点与难点¶
- 重点:判断页面是否 Ajax 动态渲染——若
requests拿到的 HTML 与浏览器看到的不一致(关键元素缺失),就要换带 JS 渲染环境的工具。 - 重点:Selenium 驱动链
Python → chromedriver → Chrome;环境配置三要素缺一不可,尤其 driver 版本必须与浏览器版本对应 且 driver 要放进 PATH。 - 易错点:
BeautifulSoup不能运行 JS,别指望它解析出 Ajax 内容。- driver 与浏览器版本不匹配会失败(83 不能配 84)。
- 运行前确认终端所在目录。
- 翻页方式是"滚动加载"而非超链接时,传统沿链接爬取的逻辑直接失效。
- Selenium 方案抓到的是真实渲染结果,与用户所见完全一致——这也是它通用性强的原因(呼应 13.5 的总结)。
关联内容¶
- 承上:13.3 静态爬取(requests + BeautifulSoup)在本课被证明对动态页面失效;13.2 的 CSS 选择器知识沿用到
find_elements_by_css_selector。 - 动态网站、Ajax、JSON 接口(
data?page=1)等概念来自上一周 Web 开发课程;演示网站即 Web 开发课做的 Flask 动态渲染站点(默认端口 5000)。 - 启下:13.5 将换一条思路——不渲染页面,直接抓取 JS 访问的数据接口;并预告后续讲真实网站案例及 IP 封禁、登录保护等对抗问题。
- 同类工具 PhantomJS 留作课后自学。