1. 项目背景与核心挑战
动态页面数据抓取一直是爬虫领域的硬骨头。传统基于requests+BeautifulSoup的静态页面爬虫在面对现代Web应用时几乎完全失效——数据显示,2023年Top 1000网站中已有83%采用动态渲染技术。某点评网这类生活服务平台的商家数据,正是通过AJAX异步加载和JavaScript动态生成的典型代表。
我最近接到的需求是要完整获取某二线城市所有餐饮商家的:基础信息(名称、地址、电话)、评分数据(口味、环境、服务)、人均消费以及最新50条用户评价。经过技术验证,发现该网站存在三重防护:
- 关键数据接口需要携带动态生成的
_token参数 - 页面元素采用CSS类名随机混淆
- 滑动验证码触发频率高达每分钟3次
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型:双引擎架构设计
2.1 为什么需要双引擎?
单纯使用Selenium面临两个致命问题:
- 执行效率低(平均每页加载需要6-8秒)
- 指纹特征明显容易被封
Playwright的优势在于:
- 支持多浏览器上下文隔离
- 自带智能等待机制
- 可模拟移动端User-Agent
但Selenium的成熟生态和XPATH定位稳定性仍不可替代。最终方案是:
- Playwright负责核心数据接口的请求伪造
- Selenium处理验证码识别和异常状态监控
2.2 环境搭建要点
python复制# 混合环境配置示例
from selenium.webdriver import ChromeOptions
from playwright.sync_api import sync_playwright
def init_engines():
# Selenium配置
chrome_options = ChromeOptions()
chrome_options.add_argument("--headless=new")
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
# Playwright配置
pw = sync_playwright().start()
browser = pw.chromium.launch(headless=False)
context = browser.new_context(
user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X)..."
)
return {
'selenium': webdriver.Chrome(options=chrome_options),
'playwright': {'instance': pw, 'context': context}
}
3. 核心破解技术实现
3.1 动态Token获取方案
通过Playwright监听网络请求发现,_token实际是调用了/api/security接口返回的加密字符串。关键实现代码:
python复制async def get_dynamic_token(page):
async with page.expect_response("**/api/security") as response_info:
await page.goto(target_url)
response = await response_info.value
return (await response.json())['token']
3.2 元素定位的终极方案
面对随机变化的CSS类名,采用组合定位策略:
- 优先使用文本内容定位
python复制# 评分元素定位示例
rating = page.locator("xpath=//*[contains(text(),'口味')]/following-sibling::span")
- 次选数据-testid属性
- 最后使用相对位置定位
3.3 验证码破解流水线
设计了三层防御体系:
- 请求频率控制(单IP < 30req/min)
- 验证码识别服务对接(使用第三方打码平台)
- 人工介入备用通道
4. 数据存储与反侦察策略
4.1 分布式存储设计
采用分片存储方案:
- MySQL存结构化数据(商家基础信息)
- MongoDB存非结构化数据(用户评价)
- 本地JSON文件作为灾备
4.2 行为伪装系统
实现了一套动态行为模式:
python复制class HumanizedOperation:
def random_scroll(self):
scroll_patterns = [
{"type": "fast", "distance": 300},
{"type": "slow", "distance": 800}
]
pattern = random.choice(scroll_patterns)
self.driver.execute_script(f"window.scrollBy(0, {pattern['distance']})")
time.sleep(pattern['distance']/1000)
5. 实战性能数据
经过两周的调优,最终达到的指标:
- 完整数据覆盖率:98.7%
- 平均单页采集时间:3.2秒
- 日均有效数据量:12万条
- 封禁率:0.3次/天
关键优化点:
- 使用Playwright的route拦截技术减少80%的冗余请求
- 实现DOM变更监听器避免轮询等待
- 开发了智能重试机制
6. 踩坑实录与解决方案
6.1 内存泄漏问题
现象:连续运行8小时后内存占用超过8GB
根因:Playwright context未及时清理
修复方案:
python复制def cleanup(context):
context.clear_cookies()
context.clear_permissions()
context.close()
6.2 元素定位失效
典型报错:ElementNotInteractableException
解决方案金字塔:
- 增加等待策略
- 尝试备用定位方式
- 刷新页面重试
- 触发强制重渲染
7. 法律合规建议
重要提示:虽然技术可实现全量采集,但务必注意:
- 严格遵守robots.txt限制
- 单日采集量控制在网站总数据量的5%以内
- 数据使用范围限于分析研究
- 关键字段做脱敏处理
这套方案经过三个月的生产验证,在保证合规的前提下,成功获取了覆盖32个城市、总计870万条的餐饮数据,为后续的商圈热力分析提供了坚实基础。对于需要处理更复杂反爬的场景,可以考虑加入WebSocket流量分析和WASM逆向模块,这将是下一步的优化方向。
