1. 项目概述与核心价值
天气预报数据抓取是Python爬虫学习的经典实战项目,但大多数教程止步于基础数据获取。这个项目将带你从零实现一个具备完整生产级功能的天气数据采集系统,不仅能自动抓取多城市未来7-15天的详细预报(包括温度、天气状况、风向等关键指标),还实现了CSV导出和SQLite持久化存储——这正是企业级数据采集系统的基础架构。
我在实际工作中开发过多个类似系统,发现新手常陷入三个误区:要么只关注数据获取忽视存储规范,要么处理不好动态网页的反爬机制,要么缺乏异常处理导致程序脆弱。本方案将特别针对这些痛点,分享经过实战检验的解决方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工具选型
2.1 基础环境配置
推荐使用Python 3.8+版本,这是目前企业环境中稳定性与兼容性最佳的版本。关键库安装命令如下:
bash复制pip install requests beautifulsoup4 pandas sqlalchemy
选型理由:
requests:比urllib更人性化的HTTP库,适合快速开发beautifulsoup4:HTML解析利器,应对多数静态页面足矣pandas:数据清洗和CSV导出的行业标准sqlalchemy:ORM工具,比直接操作SQLite接口更安全规范
2.2 目标网站分析
以中国天气网(www.weather.com.cn)为例,其数据呈现有典型特点:
- 城市页面URL格式固定:
http://www.weather.com.cn/weather/城市代码.shtml - 7天预报在静态HTML中,15天预报需调用内部API
- 关键数据藏在
<script>标签的JavaScript变量中
提示:实际开发前务必检查目标网站的robots.txt文件,遵守爬取频率限制
3. 核心爬取逻辑实现
3.1 城市代码映射处理
中国天气网使用一套内部城市编码系统,需要建立城市名到编码的映射关系。这里给出两种实用方案:
python复制# 方案1:硬编码常见城市(适合少量城市)
city_codes = {
'北京': '101010100',
'上海': '101020100',
# 补充其他城市...
}
# 方案2:动态获取(推荐)
def get_city_code(city_name):
search_url = f"http://www.weather.com.cn/search/city.shtml?cityname={city_name}"
response = requests.get(search_url)
# 解析返回页面获取真实城市代码
# 具体解析逻辑需根据实际页面结构调整
return parsed_code
3.2 页面数据解析技巧
7天天气预报的典型HTML结构如下:
html复制<ul class="t clearfix">
<li>
<h1>13日(今天)</h1>
<p title="晴" class="wea">晴</p>
<p class="tem">
<span>28</span>/<i>18</i>℃
</p>
<p class="win">
<em><span title="北风" class="N"></span></em>
<i><3级</i>
</p>
</li>
<!-- 更多天数... -->
</ul>
对应的解析代码示例:
python复制def parse_7days(html):
soup = BeautifulSoup(html, 'html.parser')
days = soup.select('ul.t li')
results = []
for day in days:
date = day.h1.text.split('(')[0]
weather = day.p['title']
temp = day.select_one('p.tem')
max_temp = temp.span.text
min_temp = temp.i.text
wind = day.select_one('p.win em span')['title']
results.append({
'date': date,
'weather': weather,
'max_temp': max_temp,
'min_temp': min_temp,
'wind': wind
})
return results
3.3 15天数据获取方案
对于15天预报,需要分析XHR请求。通过浏览器开发者工具可以发现实际数据接口类似:
code复制http://www.weather.com.cn/weather15d/101010100.shtml
返回的是JSONP格式数据,处理时需要:
python复制import re
import json
def parse_15days(html):
# 提取JSONP数据
pattern = r'var future24h = (.*?);'
match = re.search(pattern, html)
if match:
json_str = match.group(1)
data = json.loads(json_str)
# 处理data中的日期、温度等字段
return processed_data
return []
4. 数据存储模块设计
4.1 CSV导出实现
使用pandas可以优雅地处理CSV导出:
python复制import pandas as pd
def save_to_csv(data, filename):
df = pd.DataFrame(data)
# 处理中文编码问题
df.to_csv(filename, index=False, encoding='utf_8_sig')
# 验证文件可读性
test_df = pd.read_csv(filename)
assert len(test_df) > 0, "CSV导出验证失败"
注意:一定要使用utf_8_sig编码,这是Excel兼容性最好的UTF-8格式
4.2 SQLite数据库设计
建议采用以下表结构:
python复制from sqlalchemy import create_engine, Column, Integer, String, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class WeatherRecord(Base):
__tablename__ = 'weather_forecast'
id = Column(Integer, primary_key=True)
city = Column(String(50))
date = Column(Date)
weather = Column(String(20))
max_temp = Column(Integer)
min_temp = Column(Integer)
wind = Column(String(20))
created_at = Column(Date)
初始化数据库连接:
python复制def init_db(db_path):
engine = create_engine(f'sqlite:///{db_path}')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
return Session()
5. 完整系统集成
5.1 主流程控制
python复制def main(cities):
session = init_db('weather.db')
for city in cities:
try:
# 获取城市代码
code = get_city_code(city)
# 抓取7天数据
url_7d = f"http://www.weather.com.cn/weather/{code}.shtml"
html = requests.get(url_7d).text
data_7d = parse_7days(html)
# 抓取15天数据
url_15d = f"http://www.weather.com.cn/weather15d/{code}.shtml"
html = requests.get(url_15d).text
data_15d = parse_15days(html)
# 合并数据
full_data = data_7d + data_15d
# 存储到数据库
for record in full_data:
db_record = WeatherRecord(
city=city,
date=record['date'],
weather=record['weather'],
max_temp=record['max_temp'],
min_temp=record['min_temp'],
wind=record['wind'],
created_at=datetime.now()
)
session.add(db_record)
# 导出CSV
save_to_csv(full_data, f"{city}_weather.csv")
except Exception as e:
print(f"处理城市{city}时出错: {str(e)}")
continue
session.commit()
session.close()
5.2 反爬策略应对
中国天气网有基础的反爬机制,需要添加以下防护措施:
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
'Referer': 'http://www.weather.com.cn/'
}
proxies = {
'http': 'http://your_proxy:port',
'https': 'http://your_proxy:port'
}
def safe_request(url, max_retry=3):
for i in range(max_retry):
try:
response = requests.get(url, headers=headers, proxies=proxies, timeout=10)
if response.status_code == 200:
return response
time.sleep(random.uniform(1, 3))
except:
time.sleep(5)
raise Exception(f"请求失败: {url}")
6. 进阶优化方向
6.1 定时任务集成
使用APScheduler实现定时抓取:
python复制from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler()
@scheduler.scheduled_job('cron', hour=6)
def daily_job():
cities = ['北京', '上海', '广州']
main(cities)
scheduler.start()
6.2 数据可视化扩展
基于采集的数据生成温度趋势图:
python复制import matplotlib.pyplot as plt
def plot_temperature(df):
plt.figure(figsize=(12, 6))
df['date'] = pd.to_datetime(df['date'])
plt.plot(df['date'], df['max_temp'], label='最高温')
plt.plot(df['date'], df['min_temp'], label='最低温')
plt.xlabel('日期')
plt.ylabel('温度(℃)')
plt.title('未来15天温度趋势')
plt.legend()
plt.savefig('temperature_trend.png')
6.3 异常处理增强
完善的异常处理体系应包括:
- 网络请求重试机制
- 数据完整性校验
- 数据库冲突处理
- 日志记录系统
python复制import logging
logging.basicConfig(
filename='weather.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def validate_data(record):
required_fields = ['date', 'weather', 'max_temp', 'min_temp']
return all(field in record for field in required_fields)
7. 常见问题解决方案
7.1 编码问题处理
当遇到乱码时,可以尝试以下方法:
python复制# 方法1:指定响应编码
response.encoding = 'utf-8'
# 方法2:使用chardet自动检测
import chardet
encoding = chardet.detect(response.content)['encoding']
response.encoding = encoding if encoding else 'gbk'
7.2 数据不一致处理
不同城市的页面结构可能有差异,建议:
- 为每个主要城市编写适配器
- 添加数据清洗步骤:
python复制def clean_temp(temp_str):
# 处理"28℃"或"28"等不同格式
return int(re.sub(r'[^\d]', '', temp_str))
7.3 数据库性能优化
当数据量增大时:
- 使用批量插入代替单条插入
- 建立合适的索引
python复制# 批量插入示例
def bulk_insert(session, records):
session.bulk_insert_mappings(WeatherRecord, records)
session.commit()
8. 项目部署建议
8.1 Docker容器化
创建Dockerfile实现一键部署:
dockerfile复制FROM python:3.8-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]
8.2 配置管理
使用config.ini管理配置:
ini复制[database]
path = weather.db
[network]
timeout = 10
retry = 3
user_agent = Mozilla/5.0...
8.3 日志监控
配置日志轮转和监控:
python复制from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
'weather.log',
maxBytes=5*1024*1024,
backupCount=3
)
logger.addHandler(handler)
这个天气预报爬虫系统虽然看似简单,但涵盖了企业级数据采集系统的核心要素:数据获取、清洗、存储和调度。我在实际项目中总结出几个关键点:一是要建立完善的异常处理机制,二是要设计可扩展的存储方案,三是要有详细的数据质量检查流程。
