1. 项目概述:城市天气预报数据自动化采集系统
这个Python爬虫项目实现了一个完整的天气预报数据采集解决方案。用户只需输入城市名称列表,程序就能自动抓取未来7-15天的详细天气预报数据,包括日期、天气状况、温度范围和风向等关键信息。采集到的数据会同时以CSV格式导出,并存储到SQLite数据库中,方便后续分析和使用。
我在实际开发中发现,这类天气预报数据采集系统特别适合以下场景:
- 个人旅行计划时比较多个城市的天气趋势
- 农业种植需要长期天气监测
- 物流运输行业的路线天气风险评估
- 气象爱好者的数据收集与分析
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心功能与技术选型
2.1 主要功能模块分解
这个爬虫系统包含以下几个核心组件:
- 城市输入处理模块:接收并验证用户输入的城市列表
- 网络请求模块:向天气数据源发送请求并获取响应
- 数据解析模块:从HTML或JSON响应中提取所需天气信息
- 数据存储模块:实现CSV导出和SQLite数据库持久化
- 错误处理模块:处理网络异常、数据解析失败等情况
2.2 关键技术选型与考量
选择Python作为开发语言主要基于以下考虑:
- Requests库:相比urllib更简洁的API,自动处理编码问题
- BeautifulSoup4:强大的HTML解析能力,支持多种解析器
- Pandas:简化CSV文件的读写操作
- SQLite3:轻量级数据库,无需额外服务,适合小型项目
提示:在实际项目中,我建议使用fake-useragent库来随机生成User-Agent,可以有效降低被反爬的风险。
3. 详细实现步骤
3.1 环境准备与依赖安装
首先需要安装必要的Python库:
bash复制pip install requests beautifulsoup4 pandas
对于SQLite支持,Python标准库已经包含sqlite3模块,无需额外安装。
3.2 网络请求模块实现
python复制import requests
from fake_useragent import UserAgent
def fetch_weather_data(city):
ua = UserAgent()
headers = {
'User-Agent': ua.random,
'Accept-Language': 'zh-CN,zh;q=0.9'
}
try:
# 这里需要替换为实际的天气API或网页URL
url = f"https://weather.example.com/search?city={city}"
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"获取{city}天气数据失败: {e}")
return None
3.3 数据解析模块实现
假设我们从HTML页面解析数据:
python复制from bs4 import BeautifulSoup
import re
def parse_weather_data(html, city):
soup = BeautifulSoup(html, 'html.parser')
weather_data = []
# 查找包含天气预报的HTML元素
forecast_items = soup.select('.forecast-item')
for item in forecast_items:
date = item.select_one('.date').text.strip()
condition = item.select_one('.condition').text.strip()
temp_range = item.select_one('.temp-range').text.strip()
# 使用正则表达式提取温度数值
match = re.search(r'(\d+)℃/(\d+)℃', temp_range)
if match:
high_temp = match.group(1)
low_temp = match.group(2)
wind = item.select_one('.wind').text.strip()
weather_data.append({
'city': city,
'date': date,
'condition': condition,
'high_temp': high_temp,
'low_temp': low_temp,
'wind': wind
})
return weather_data
3.4 数据存储模块实现
CSV导出实现
python复制import pandas as pd
def save_to_csv(weather_data, filename='weather_forecast.csv'):
df = pd.DataFrame(weather_data)
# 确保中文正常显示
df.to_csv(filename, index=False, encoding='utf-8-sig')
print(f"数据已保存到{filename}")
SQLite数据库存储实现
python复制import sqlite3
from datetime import datetime
def init_db(db_name='weather.db'):
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS weather_forecast (
id INTEGER PRIMARY KEY AUTOINCREMENT,
city TEXT NOT NULL,
date TEXT NOT NULL,
condition TEXT,
high_temp INTEGER,
low_temp INTEGER,
wind TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
return conn
def save_to_db(conn, weather_data):
cursor = conn.cursor()
for data in weather_data:
cursor.execute('''
INSERT INTO weather_forecast
(city, date, condition, high_temp, low_temp, wind)
VALUES (?, ?, ?, ?, ?, ?)
''', (
data['city'],
data['date'],
data['condition'],
data['high_temp'],
data['low_temp'],
data['wind']
))
conn.commit()
print(f"已保存{len(weather_data)}条数据到数据库")
4. 完整流程整合
python复制def main():
cities = input("请输入城市名称,多个城市用逗号分隔: ").split(',')
all_weather_data = []
# 初始化数据库连接
conn = init_db()
for city in cities:
city = city.strip()
print(f"正在获取{city}的天气预报...")
html = fetch_weather_data(city)
if html:
weather_data = parse_weather_data(html, city)
if weather_data:
all_weather_data.extend(weather_data)
save_to_db(conn, weather_data)
if all_weather_data:
save_to_csv(all_weather_data)
conn.close()
print("天气预报数据采集完成!")
if __name__ == '__main__':
main()
5. 常见问题与解决方案
5.1 反爬虫机制应对策略
-
User-Agent限制:
- 使用fake-useragent库随机生成
- 定期更新useragent列表
-
IP封锁问题:
- 添加请求延迟:
time.sleep(random.uniform(1, 3)) - 考虑使用代理IP池(需遵守目标网站的使用条款)
- 添加请求延迟:
-
验证码挑战:
- 对于简单验证码可尝试OCR识别
- 复杂验证码建议人工处理或寻找替代数据源
5.2 数据解析失败处理
在实际操作中,我遇到过几种常见的解析问题:
- HTML结构变化:
- 使用更通用的CSS选择器,避免过于具体的路径
- 添加try-except块捕获解析异常
python复制try:
date = item.select_one('.date').text.strip()
except AttributeError:
date = '未知'
- 数据格式不一致:
- 添加数据清洗步骤,统一温度单位等
- 使用正则表达式提取关键数值
5.3 数据存储优化建议
-
CSV文件中文乱码:
- 使用
utf-8-sig编码而非普通utf-8 - 在Excel中导入时选择正确编码
- 使用
-
SQLite性能优化:
- 使用事务批量插入数据
- 考虑添加适当索引提高查询速度
python复制# 批量插入示例
def batch_save_to_db(conn, weather_data, batch_size=100):
cursor = conn.cursor()
for i in range(0, len(weather_data), batch_size):
batch = weather_data[i:i+batch_size]
cursor.executemany('''
INSERT INTO weather_forecast
(city, date, condition, high_temp, low_temp, wind)
VALUES (?, ?, ?, ?, ?, ?)
''', [
(data['city'], data['date'], data['condition'],
data['high_temp'], data['low_temp'], data['wind'])
for data in batch
])
conn.commit()
6. 项目扩展与进阶建议
6.1 功能扩展方向
-
可视化展示:
- 使用Matplotlib绘制温度变化曲线
- 生成天气日历视图
-
异常天气预警:
- 检测极端温度或恶劣天气
- 集成邮件或短信通知功能
-
历史数据对比:
- 存储历史天气数据
- 实现同期天气比较功能
6.2 代码优化建议
-
配置化管理:
- 将城市列表、请求头等移入配置文件
- 使用configparser或JSON配置文件
-
日志记录:
- 添加详细的运行日志
- 记录成功和失败的请求
python复制import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='weather_spider.log'
)
def fetch_weather_data(city):
try:
# ...原有代码...
logging.info(f"成功获取{city}天气数据")
except Exception as e:
logging.error(f"获取{city}天气数据失败: {str(e)}")
- 单元测试:
- 为关键函数添加测试用例
- 使用unittest或pytest框架
7. 实际应用中的经验分享
在开发这个天气预报爬虫的过程中,我积累了一些宝贵的实战经验:
-
请求频率控制:
- 过快请求会导致IP被封,建议每个请求间隔2-5秒
- 对于大量城市,考虑使用队列和线程池控制并发
-
数据源选择:
- 优先选择提供API接口的官方数据源
- 如果没有API,选择结构稳定的网页版
-
数据验证:
- 添加基本的数据合理性检查
- 如温度范围(-50℃到50℃)、天气状况枚举值等
python复制VALID_CONDITIONS = ['晴', '多云', '阴', '雨', '雪', '雾']
def validate_weather_data(data):
if not -50 <= int(data['high_temp']) <= 50:
return False
if data['condition'] not in VALID_CONDITIONS:
return False
return True
- 异常处理:
- 网络请求设置合理的超时时间
- 实现自动重试机制
python复制def fetch_with_retry(url, max_retries=3):
for attempt in range(max_retries):
try:
return requests.get(url, timeout=10)
except requests.exceptions.Timeout:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
这个天气预报爬虫项目虽然看似简单,但涵盖了Python爬虫开发的多个关键技术点。通过这个项目,我们不仅学会了如何获取和解析网页数据,还掌握了数据持久化的两种常用方式。最重要的是,我们了解了如何构建一个健壮的爬虫系统,能够处理各种异常情况。
