用Requests+BeautifulSoup实现天气预报数据采集:从入门到实战
目录
一、为什么选择Requests+BeautifulSoup组合?
二、环境准备与基础代码
1. 安装必要库
2. 基础请求代码
三、HTML解析与数据提取
1. 分析页面结构
2. 完整解析代码
3. 优化技巧
四、完整采集流程
五、进阶优化方向
1. 多城市采集
2. 定时采集
3. 数据可视化
六、常见问题Q&A
七、总结与展望
免费编程软件「python+pycharm」
链接:https://pan.quark.cn/s/48a86be2fdc0
在数据驱动的时代,天气预报数据是气象分析、农业规划、物流调度等场景的重要基础。本文将通过一个完整案例,教你如何用Python的Requests库获取网页内容,再用BeautifulSoup解析HTML,最终实现天气预报数据的自动化采集。整个过程不涉及复杂理论,只讲实战技巧,即使你是编程新手也能轻松上手。
一、为什么选择Requests+BeautifulSoup组合?
在Python爬虫领域,Scrapy框架功能强大但学习曲线陡峭,Selenium能处理动态页面但效率较低。对于天气预报这类结构化数据采集,Requests+BeautifulSoup的组合具有显著优势:
- 轻量高效:Requests负责HTTP请求,BeautifulSoup专注解析,两者配合内存占用小
- 开发快速:30行代码就能实现基础功能,适合快速验证需求
- 维护简单:代码可读性强,便于后续修改和扩展
以中国天气网为例,其省级天气页面采用标准HTML结构,非常适合用这种组合采集。我们以采集"北京市天气预报"为例,展示完整实现过程。
二、环境准备与基础代码
1. 安装必要库
pip install requests beautifulsoup4 fake-useragent
requests
:发送HTTP请求beautifulsoup4
:解析HTMLfake-useragent
:生成随机User-Agent(反爬必备)
2. 基础请求代码
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgentdef get_weather_page(url):headers = {'User-Agent': UserAgent().random}try:response = requests.get(url, headers=headers, timeout=10)response.raise_for_status() # 检查请求是否成功response.encoding = 'utf-8' # 设置编码return response.textexcept requests.exceptions.RequestException as e:print(f"请求失败: {e}")return None# 测试请求
url = "http://www.weather.com.cn/textFC/hb.shtml" # 华北地区天气
html_content = get_weather_page(url)
if html_content:print("获取页面成功")
关键点说明:
- 随机User-Agent模拟不同浏览器访问
- 设置超时时间防止程序卡死
- 统一编码避免中文乱码
- 异常处理确保程序健壮性
三、HTML解析与数据提取
1. 分析页面结构
打开中国天气网华北地区页面,右键检查元素,找到天气数据所在的HTML结构:
<div class="conMidtab"><div class="conMidtab2"><table class="twoInner"><tr><td class="time">08时</td><td>晴</td><td>-2℃</td><td>3级</td></tr><!-- 更多行... --></table></div>
</div>
关键特征:
- 天气数据在
class="twoInner"
的表格中 - 每行数据包含时间、天气现象、温度、风力
2. 完整解析代码
def parse_weather_data(html):soup = BeautifulSoup(html, 'html.parser')table = soup.find('table', class_='twoInner')if not table:print("未找到天气表格")return []weather_data = []rows = table.find_all('tr')[1:] # 跳过表头for row in rows:cols = row.find_all('td')if len(cols) >= 4:data = {'time': cols[0].get_text(strip=True),'weather': cols[1].get_text(strip=True),'temperature': cols[2].get_text(strip=True),'wind': cols[3].get_text(strip=True)}weather_data.append(data)return weather_data# 测试解析
if html_content:data = parse_weather_data(html_content)for item in data[:3]: # 打印前3条print(item)
输出示例:
{'time': '08时', 'weather': '晴', 'temperature': '-2℃', 'wind': '3级'}
{'time': '11时', 'weather': '晴', 'temperature': '3℃', 'wind': '2级'}
{'time': '14时', 'weather': '多云', 'temperature': '5℃', 'wind': '2级'}
3. 优化技巧
- 容错处理:检查
table
是否存在,避免程序崩溃 - 数据清洗:使用
get_text(strip=True)
去除空白字符 - 结构化输出:将每行数据转为字典,便于后续处理
四、完整采集流程
将上述代码整合为完整脚本,并添加数据存储功能:
import csv
from datetime import datetimedef save_to_csv(data, filename='weather.csv'):if not data:print("无数据可保存")return# 添加采集时间for item in data:item['update_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')# 写入CSV文件with open(filename, 'w', newline='', encoding='utf-8-sig') as f:writer = csv.DictWriter(f, fieldnames=data[0].keys())writer.writeheader()writer.writerows(data)print(f"数据已保存到 {filename}")def main():url = "http://www.weather.com.cn/textFC/hb.shtml"html = get_weather_page(url)if html:data = parse_weather_data(html)save_to_csv(data)if __name__ == '__main__':main()
执行结果:
程序会在当前目录生成weather.csv文件,包含采集时间和所有天气数据。
五、进阶优化方向
1. 多城市采集
通过修改URL参数实现:
CITIES = {'北京': 'hb.shtml', # 华北'上海': 'hd.shtml', # 华东# 添加更多城市...
}def batch_collect():for city, path in CITIES.items():url = f"http://www.weather.com.cn/textFC/{path}"html = get_weather_page(url)if html:data = parse_weather_data(html)for item in data:item['city'] = city # 添加城市字段save_to_csv(data, f'weather_{city.lower()}.csv')
2. 定时采集
使用schedule
库实现每天8点自动采集:
import schedule
import timedef job():print("开始定时采集...")main()schedule.every().day.at("08:00").do(job)while True:schedule.run_pending()time.sleep(60)
3. 数据可视化
用Matplotlib简单绘制温度变化曲线:
import matplotlib.pyplot as pltdef plot_temperature(data):times = [item['time'] for item in data]temps = [int(item['temperature'].replace('℃', '')) for item in data]plt.figure(figsize=(10, 4))plt.plot(times, temps, marker='o')plt.title('北京今日温度变化')plt.xlabel('时间')plt.ylabel('温度(℃)')plt.grid(True)plt.savefig('temperature.png')plt.show()
六、常见问题Q&A
Q1:被网站封IP怎么办?
A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。更简单的方案是设置请求间隔:
import time
import randomdef safe_request(url):time.sleep(random.uniform(1, 3)) # 随机延迟1-3秒return get_weather_page(url)
Q2:网站结构变了怎么办?
A:定期检查解析代码是否还能正常工作。建议:
- 将选择器(如
class_='twoInner'
)提取为配置变量 - 添加页面结构校验逻辑
- 使用
try-except
捕获解析异常
Q3:如何采集动态加载的数据?
A:对于JavaScript渲染的数据,有两种方案:
- 分析接口:用浏览器开发者工具查找数据API(推荐)
- Selenium模拟:对复杂页面可使用Selenium+WebDriver
Q4:采集频率应该设置多少?
A:遵循robots.txt协议和网站服务条款。一般建议:
- 公开数据:每小时不超过1次
- 商业数据:联系网站获取授权
- 添加随机延迟避免规律性请求
Q5:如何存储大量历史数据?
A:根据数据量选择:
- 小规模:CSV/Excel
- 中等规模:SQLite数据库
- 大规模:MySQL/MongoDB等专业数据库
七、总结与展望
通过本文,你已掌握:
- 使用Requests发送HTTP请求
- 用BeautifulSoup解析HTML
- 提取结构化天气数据
- 存储和可视化数据
- 常见问题的解决方案
实际应用中,你可能需要处理:
- 登录验证
- 验证码识别
- 分布式采集
- 数据去重
建议从简单需求开始,逐步添加复杂功能。记住:爬虫开发的核心是模拟人类浏览行为,保持请求的随机性和合理性是长期运行的关键。