当前位置:首页 > 前端开发 > 正文

js生成的html如何爬取

需用 Selenium/Puppeteer 等工具模拟浏览器执行

核心挑战:为何传统爬虫失效?

现代网页普遍采用异步加载技术(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):

js生成的html如何爬取 第1张

优势:原生支持异步API,内置截图/PDF生成功能

性能提升:相比Selenium快3-5倍,内存占用降低60%

方案3:逆向分析API接口(高效首选)

核心思路:通过开发者工具找到数据源接口,直连后端服务

操作流程

  1. 打开浏览器F12 → Network面板
  2. 刷新页面 → 筛选XHR/fetch请求
  3. 识别返回JSON/数据的请求URL
  4. 构造请求参数(注意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生成的html如何爬取 第2张

优势:毫秒级响应,无需渲染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接口
  • 需要登录态才能访问

混合方案设计

js生成的html如何爬取 第3张

  1. 使用Selenium登录获取Cookie
  2. 提取Cookie中的auth_token
  3. 改用requests直接调用API接口
  4. 并行多线程采集(控制并发数≤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: 为什么有时能抓到数据,有时抓不到?

原因分析

  1. 时机问题:JS执行未完成即开始解析(解决方案:增加等待时间/监听事件)
  2. 环境差异:本地IP被屏蔽(解决方案:启用高质量代理)
  3. 版本冲突:网站检测到自动化工具特征(解决方案:更新User-Agent/禁用图片加载)
  4. 缓存机制:第一次访问成功后续失败(解决方案:强制刷新Ctrl+F5)

排查步骤

① 手动复制目标元素的XPath到浏览器控制台测试有效性

② 在代码中插入print(len(driver.find_elements(...)))验证元素数量

③ 启用日志记录(logging模块)追踪完整请求流程

Q2: 如何处理动态加载的图片/视频地址?

技术路线

  1. 拦截网络请求:使用Mitmproxy中间人代理截获媒体资源URL
  2. 延迟加载检测:通过IntersectionObserverAPI判断元素是否进入视口
  3. 懒加载免费:修改img标签的data-src属性为src后重新加载
  4. WebSocket监控:对实时推送类应用(如直播弹幕)建立长连接监听

代码示例(修改懒加载)

// 在Page对象创建后载入脚本 await page.evaluate(() => { const lazyImages = document.querySelectorAll('img[data-src]'); lazyImages.forEach(img => { img.src = img.dataset.src; }); });


伦理与法律提示

  1. robots.txt协议:遵守/robots.txt文件中的规则(可通过requests.get("https://example.com/robots.txt")查看)
  2. 版权风险:商业用途需获得网站授权(《著作权法》第10条)
  3. 个人隐私:避免采集敏感信息(身份证号/手机号等),违反《个人信息保护法》
  4. 技术底线:禁止突破网站安全防护(如绕过支付验证流程)

建议将采集频率控制在合理范围(一般不超过1次/秒),必要时联系网站管理员

0