1. 项目概述:城市景点数据采集器
这个Python爬虫项目能根据用户输入的城市名称,自动抓取该城市热门景点的三大核心数据:景点名称、大众评分(星级)和详细地址。最终数据会整理成结构化的CSV文件,方便后续分析或导入其他系统。我在实际旅游行业数据采集中多次使用类似方案,相比手动收集效率提升20倍以上。
数据采集目标包含三个关键字段:
- 景点名称(如"故宫博物院")
- 评分星级(如4.7/5分)
- 地理地址(如"北京市东城区景山前街4号")
CSV导出功能让数据能直接用于Excel分析、数据库导入或地图标注。这个工具特别适合:
- 旅游行业从业者做竞品分析
- 本地生活类APP的POI数据补充
- 个人旅行前的行程规划
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术方案设计
2.1 目标网站选择策略
经过实测对比多个旅游平台,建议优先选择大众点评/美团作为数据源,原因有三:
- 数据完整性:覆盖全国95%以上城市的景点信息
- 反爬友好度:相比某些平台,验证机制相对宽松
- 数据结构化:页面元素class命名规范,便于解析
重要提示:实际采集时建议控制请求频率(每秒不超过2次),并在请求头中添加合理的User-Agent
2.2 核心工具链配置
python复制# 基础环境需求
import requests # 网络请求
from bs4 import BeautifulSoup # HTML解析
import pandas as pd # 数据处理
import csv # 文件导出
import time # 请求间隔控制
import re # 正则匹配
推荐使用虚拟环境安装依赖:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
pip install requests beautifulsoup4 pandas
3. 爬虫核心实现
3.1 网页请求与反爬应对
python复制def get_html(city):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
url = f"https://www.dianping.com/{city}/ch10" # 大众点评景点分类页
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.text
except Exception as e:
print(f"请求失败: {e}")
return None
关键点说明:
- 动态构造URL:将城市名拼接到固定URL模式中
- 请求头伪装:模拟浏览器访问特征
- 异常处理:应对网络波动和反爬拦截
3.2 数据解析技巧
python复制def parse_html(html):
soup = BeautifulSoup(html, 'html.parser')
spots = []
for item in soup.select('.shop-list li'):
try:
name = item.select_one('.tit a').text.strip()
rating = item.select_one('.comment span').text
address = item.select_one('.addr').text
spots.append([name, rating, address])
except AttributeError:
continue
return spots
解析注意事项:
- 使用CSS选择器定位元素更稳定
- 每个字段提取都应有try-catch保护
- 文本处理注意去除首尾空白字符
3.3 数据存储优化
python复制def save_to_csv(data, filename):
columns = ['景点名称', '评分', '地址']
df = pd.DataFrame(data, columns=columns)
# 中文编码处理
df.to_csv(filename, index=False, encoding='utf_8_sig')
print(f"数据已保存到 {filename}")
文件存储要点:
- 使用utf_8_sig编码解决Excel中文乱码
- 添加明确的列标题
- 禁用自动索引(index=False)
4. 完整工作流整合
python复制def main():
city = input("请输入城市名称(如beijing): ")
html = get_html(city)
if not html:
return
spots = parse_html(html)
if not spots:
print("未找到景点数据,请检查城市名称")
return
timestamp = time.strftime("%Y%m%d_%H%M")
filename = f"{city}_spots_{timestamp}.csv"
save_to_csv(spots, filename)
if __name__ == "__main__":
main()
执行流程说明:
- 交互式输入城市拼音
- 自动生成带时间戳的文件名
- 完整错误处理链条
5. 高级技巧与问题排查
5.1 分页采集实现
python复制def get_all_pages(city, max_pages=5):
all_spots = []
for page in range(1, max_pages+1):
url = f"https://www.dianping.com/{city}/ch10/p{page}"
html = get_html(url)
if html:
all_spots.extend(parse_html(html))
time.sleep(1) # 页间延迟
return all_spots
分页控制要点:
- 观察URL分页规律(通常为p1/p2)
- 设置合理的页数限制
- 必须添加页间延迟
5.2 常见问题解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 返回403错误 | IP被暂时封禁 | 1. 增加请求头信息 2. 使用代理IP 3. 降低采集频率 |
| 数据缺失 | 页面结构变化 | 1. 更新CSS选择器 2. 添加更多容错处理 |
| 中文乱码 | 编码不一致 | 1. 统一使用utf-8 2. 文件保存用utf_8_sig |
| 验证码拦截 | 触发反爬 | 1. 模拟登录获取cookie 2. 使用selenium模拟人工操作 |
5.3 数据清洗技巧
原始数据常需要后处理:
- 评分标准化:将"4.5/5分"转为数值4.5
- 地址补全:部分地址缺少城市名,需自动补全
- 去重处理:同一景点可能出现在多页
python复制# 评分清洗示例
def clean_rating(rating_str):
try:
return float(re.search(r'(\d\.\d)', rating_str).group(1))
except:
return None
6. 项目扩展方向
- 地理编码扩展:通过百度/高德API将地址转为经纬度
- 图片采集:下载景点封面图片
- 评论情感分析:采集并分析用户评价
- 自动化更新:设置定时任务每天采集最新数据
python复制# 地理编码示例(需申请API key)
def get_coordinates(address):
api_url = "https://restapi.amap.com/v3/geocode/geo"
params = {
'address': address,
'key': 'your_api_key'
}
response = requests.get(api_url, params=params)
return response.json().get('geocodes', [{}])[0].get('location')
实际部署建议:
- 使用代理IP池应对大规模采集
- 考虑使用Scrapy框架提升效率
- 重要数据建议存储到数据库而非CSV
