js生成的html如何爬取
- 前端开发
- 2025-08-17
- 6
核心挑战:为何传统爬虫失效?
现代网页普遍采用异步加载技术(AJAX/Fetch API),其本质特征为:
| 现象类型 | 表现形式 | 技术根源 |
|—————-|——————————|————————|
| 空白初始页面 | 首次请求仅返回空容器/占位符 | DOM由JS动态构建 |
| XHR二次请求 | 网络面板可见额外API调用 | XMLHttpRequest/fetch|
| 加密数据流 | 响应体为二进制密文 | WebAssembly/WASM沙箱 |
| 单页应用(SPA) | URL不变但内容切换 | History API路由控制 |
传统爬虫(如requests+BeautifulSoup)只能获取初始HTML骨架,无法直接捕获后续JS生成的内容,需采用能模拟浏览器行为的方案。
四大主流解决方案深度对比
方案1:Selenium + ChromeDriver(全能型)
适用场景:复杂交互式页面(表单提交/滚动加载/弹窗处理)
工作原理:启动真实Chrome实例,完全复现用户操作环境
️ 实施步骤:
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager import time # 配置无头模式(可选) options = webdriver.ChromeOptions() options.add_argument('--headless') # 后台运行 options.add_argument('--disable-gpu') # 初始化驱动 driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) try: driver.get("https://example.com") # 目标网址 time.sleep(3) # 等待JS执行完成(可根据需求调整) # 获取渲染后的页面源码 html_content = driver.page_source # 此处可接续解析逻辑(BS4/lxml等) finally: driver.quit()
优势:支持CSS选择器/XPath定位,可模拟点击/输入等操作
️ 缺点:资源占用高(约500MB内存),速度较慢(冷启动~2秒)
方案2:Pyppeteer/Playwright(轻量化替代)
适用场景:中等复杂度页面,追求更快速度
工作原理:基于Chromium内核的轻量级浏览器引擎
代码示例(Playwright):

优势:原生支持异步API,内置截图/PDF生成功能
性能提升:相比Selenium快3-5倍,内存占用降低60%
方案3:逆向分析API接口(高效首选)
核心思路:通过开发者工具找到数据源接口,直连后端服务
操作流程:
- 打开浏览器F12 → Network面板
- 刷新页面 → 筛选XHR/fetch请求
- 识别返回JSON/数据的请求URL
- 构造请求参数(注意Cookie/Headers)
典型请求头构造示例:
| 字段 | 值 | 说明 |
|—————|——————————|————————–|
| User-Agent | Mozilla/5.0 (Windows NT...) | 模拟浏览器访问 |
| Referer | https://example.com/list | 防盗链机制 |
| Cookie | sessionid=xxx; token=yyy | 身份验证凭证 |
| Content-Type | application/json | POST请求常见类型 |
代码实现(requests):

优势:毫秒级响应,无需渲染JS,适合大规模采集
️ 限制:部分网站采用JWT令牌/非对称加密,需免费签名算法
方案4:PhantomJS(淘汰预警)
现状:已停止维护,存在安全漏洞,推荐迁移至上述方案
关键技术增强点
智能等待策略
| 方法 | 适用场景 | 代码片段 |
|---|---|---|
| time.sleep() | 简单粗暴(不推荐) | time.sleep(5) |
| 显式等待(Explicit) | 特定元素出现 | WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "main"))) |
| 隐式等待(Implicit) | 全局超时设置 | driver.implicitly_wait(10) |
| 滚动触发加载 | 无限滚动列表 | driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") |
反爬对抗策略
| 威胁类型 | 解决方案 | 实施方式 |
|---|---|---|
| IP封禁 | 代理池轮换 | 集成ProxyMesh/Luminati代理服务 |
| 人机验证 | 打码平台/AI识别 | Tesseract OCR + 第三方验证码免费 |
| 请求频率限制 | 随机延迟+分布式节点 | random.uniform(1,3)间隔请求 |
| 指纹追踪 | 动态UA/Canvas指纹混淆 | fake_useragent库 + Stealthy模块 |
数据解析优化
- 正则表达式:适用于非标准HTML结构(如<script>标签内的JSONP数据)
- JsonPath:比XPath更适合处理嵌套JSON数据
- AST解析:对付混淆过的JS代码(需借助esprima等库)
实战案例:电商评论爬取
假设目标站点特点:
- 评论通过滚动加载(无限下拉)
- 数据来源于/comments?pid=XXX&page=Y接口
- 需要登录态才能访问
混合方案设计:

- 使用Selenium登录获取Cookie
- 提取Cookie中的auth_token
- 改用requests直接调用API接口
- 并行多线程采集(控制并发数≤5)
关键代码片段:
# Step1: Selenium登录获取Cookie driver.get("https://login.example.com") driver.find_element(By.NAME, "username").send_keys("user") driver.find_element(By.NAME, "pwd").send_keys("pass") driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click() cookies = driver.get_cookies() # Step2: 构造API请求 session = requests.Session() for cookie in cookies: session.cookies.set(cookie['name'], cookie['value']) # Step3: 批量采集评论 results = [] for page in range(1, 10): url = f"https://api.example.com/comments?pid=123&page={page}" resp = session.get(url, headers={"Accept": "application/json"}) results.extend(resp.json()["data"])
常见问题FAQs
Q1: 为什么有时能抓到数据,有时抓不到?
原因分析:
- 时机问题:JS执行未完成即开始解析(解决方案:增加等待时间/监听事件)
- 环境差异:本地IP被屏蔽(解决方案:启用高质量代理)
- 版本冲突:网站检测到自动化工具特征(解决方案:更新User-Agent/禁用图片加载)
- 缓存机制:第一次访问成功后续失败(解决方案:强制刷新Ctrl+F5)
排查步骤:
① 手动复制目标元素的XPath到浏览器控制台测试有效性
② 在代码中插入print(len(driver.find_elements(...)))验证元素数量
③ 启用日志记录(logging模块)追踪完整请求流程
Q2: 如何处理动态加载的图片/视频地址?
技术路线:
- 拦截网络请求:使用Mitmproxy中间人代理截获媒体资源URL
- 延迟加载检测:通过IntersectionObserverAPI判断元素是否进入视口
- 懒加载免费:修改img标签的data-src属性为src后重新加载
- WebSocket监控:对实时推送类应用(如直播弹幕)建立长连接监听
代码示例(修改懒加载):
// 在Page对象创建后载入脚本 await page.evaluate(() => { const lazyImages = document.querySelectorAll('img[data-src]'); lazyImages.forEach(img => { img.src = img.dataset.src; }); });
伦理与法律提示
- robots.txt协议:遵守/robots.txt文件中的规则(可通过requests.get("https://example.com/robots.txt")查看)
- 版权风险:商业用途需获得网站授权(《著作权法》第10条)
- 个人隐私:避免采集敏感信息(身份证号/手机号等),违反《个人信息保护法》
- 技术底线:禁止突破网站安全防护(如绕过支付验证流程)
建议将采集频率控制在合理范围(一般不超过1次/秒),必要时联系网站管理员