1. 项目背景与需求分析
大众点评作为国内领先的本地生活信息平台,积累了海量商家数据。这些数据对于市场分析、竞品调研、商业决策具有重要价值。但平台本身并未提供完整的商家数据导出接口,这催生了第三方数据采集工具的需求。
我在实际项目中开发的这套采集助手,核心目标是实现:
- 全自动化采集商家基础信息(名称、地址、联系方式)
- 动态获取实时评价数据(评分、评论内容、用户标签)
- 结构化存储采集结果便于后续分析
- 规避平台反爬机制保证长期稳定运行
提示:此类工具开发需特别注意法律边界,仅限采集公开数据且不得用于商业牟利。建议控制在个人学习研究范围内使用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 整体架构分层
采用分层架构设计,各模块解耦:
code复制数据采集层 → 数据处理层 → 存储层 → 应用层
- 采集层:基于DrissionPage实现浏览器自动化
- 处理层:使用BeautifulSoup+lxml解析HTML
- 存储层:MySQL关系型数据库+CSV文件双备份
- 应用层:Flask提供简易管理界面
2.2 核心组件选型
2.2.1 DrissionPage深度应用
相比传统Selenium方案,DrissionPage具有显著优势:
- 直接基于Chromium内核,无需额外驱动
- 内置智能等待和元素定位策略
- 支持混合模式(同时操作DOM和网络请求)
关键配置示例:
python复制from DrissionPage import ChromiumPage
page = ChromiumPage()
page.get('https://www.dianping.com')
page.wait.ele_loaded('tag:div@class=shop-list') # 智能等待店铺列表加载
2.2.2 反反爬策略设计
大众点评采用多重反爬机制:
- 行为验证(滑块/点选)
- 请求频率检测
- Cookie有效性验证
应对方案:
- 请求间隔随机化(2-5秒)
- 代理IP轮换(使用芝麻代理API)
- 模拟真人操作轨迹(随机滚动、鼠标移动)
3. 核心模块实现
3.1 商家列表采集模块
采用广度优先搜索策略:
- 通过地区分类入口获取初始列表
- 解析分页按钮实现自动翻页
- 提取每家店铺的详情页URL
关键代码片段:
python复制def get_shop_links(page):
while True:
shops = page.eles('tag:div@class=shop-item')
for shop in shops:
yield shop('tag:a@class=shop-name').attr('href')
if not page('tag:a@class=next-page'):
break
page('tag:a@class=next-page').click()
time.sleep(random.uniform(2, 4))
3.2 详情页解析模块
使用XPath精准定位关键字段:
python复制def parse_shop_detail(page):
return {
'name': page('xpath://h1[@class="shop-name"]').text,
'address': page('xpath://span[@class="address"]').text,
'phone': page('xpath://p[@class="phone"]').text,
'rating': float(page('xpath://span[@class="score"]').text),
'reviews': int(page('xpath://span[@class="count"]').text[:-3])
}
3.3 数据存储模块
采用双写策略保证数据安全:
python复制def save_data(data):
# MySQL存储
with mysql_conn.cursor() as cursor:
cursor.execute("""
INSERT INTO shops
(name, address, phone, rating, reviews)
VALUES (%s, %s, %s, %s, %s)
""", (data['name'], data['address'],
data['phone'], data['rating'],
data['reviews']))
# CSV备份
with open('backup.csv', 'a') as f:
writer = csv.writer(f)
writer.writerow(data.values())
4. 关键问题与解决方案
4.1 验证码触发机制
现象:连续采集约20家店铺后触发验证
解决方案:
- 每采集15家店铺主动更换IP
- 模拟人工操作间隔(随机停留3-8秒)
- 使用打码平台备用方案(如超级鹰)
4.2 动态加载内容缺失
现象:部分评价数据需要滚动加载
解决方案:
python复制page.scroll.to_bottom() # 滚动到底部
page.wait(3000) # 等待3秒加载
reviews = page.eles('tag:div@class=review-item')
4.3 数据字段变异
现象:页面结构不定期调整导致解析失败
解决方案:
- 建立字段映射配置表
- 实现自动重试+人工干预机制
- 邮件报警通知异常情况
5. 性能优化实践
5.1 并行采集设计
采用生产者-消费者模式:
- 1个主进程负责发现店铺链接
- 3个工作进程并行处理详情页
python复制from multiprocessing import Pool
def worker(url):
page = ChromiumPage()
page.get(url)
return parse_shop_detail(page)
with Pool(3) as p:
results = p.map(worker, shop_urls)
5.2 断点续采实现
通过Redis记录采集状态:
python复制import redis
r = redis.Redis()
def mark_done(shop_id):
r.sadd('collected_shops', shop_id)
def is_done(shop_id):
return r.sismember('collected_shops', shop_id)
5.3 资源监控体系
使用psutil监控系统资源:
python复制import psutil
def check_system():
return {
'cpu': psutil.cpu_percent(),
'memory': psutil.virtual_memory().percent,
'disk': psutil.disk_usage('/').percent
}
6. 部署与维护方案
6.1 服务化部署
使用systemd管理后台服务:
ini复制# /etc/systemd/system/dianping_crawler.service
[Unit]
Description=Dianping Data Collector
[Service]
ExecStart=/usr/bin/python3 /opt/crawler/main.py
Restart=always
User=crawler
[Install]
WantedBy=multi-user.target
6.2 日志监控
采用ELK栈实现日志集中管理:
- Filebeat收集日志
- Logstash解析字段
- Elasticsearch存储
- Kibana可视化
6.3 异常预警
通过Prometheus+Alertmanager实现:
- 采集频率异常报警
- 成功率下降报警
- 资源占用超标报警
7. 法律合规建议
- 严格遵守robots.txt限制
- 单IP请求频率控制在30次/分钟以下
- 采集数据仅用于个人研究
- 不破解任何加密接口
- 不存储用户隐私数据
实际测试表明,这套架构在保持每天采集2000家店铺数据的情况下,能稳定运行30天以上不被封禁。核心在于模拟真实用户行为模式,而非暴力爬取。建议开发者始终遵循最小必要原则,控制采集范围和频率。
