用Requests+BeautifulSoup实现天气预报数据采集:从入门到实战

在数据驱动的时代,天气预报数据是气象分析、农业规划、物流调度等场景的重要基础。本文将通过一个完整案例,教你如何用Python的Requests库获取网页内容,再用BeautifulSoup解析HTML,最终实现天气预报数据的自动化采集。整个过程不涉及复杂理论,只讲实战技巧,即使你是编程新手也能轻松上手。

一、为什么选择Requests+BeautifulSoup组合?

在Python爬虫领域,Scrapy框架功能强大但学习曲线陡峭,Selenium能处理动态页面但效率较低。对于天气预报这类结构化数据采集,Requests+BeautifulSoup的组合具有显著优势:

  1. 轻量高效:Requests负责HTTP请求,BeautifulSoup专注解析,两者配合内存占用小
  2. 开发快速:30行代码就能实现基础功能,适合快速验证需求
  3. 维护简单:代码可读性强,便于后续修改和扩展

以中国天气网为例,其省级天气页面采用标准HTML结构,非常适合用这种组合采集。我们以采集"北京市天气预报"为例,展示完整实现过程。

二、环境准备与基础代码

1. 安装必要库

复制代码
pip install requests beautifulsoup4 fake-useragent
  • requests:发送HTTP请求
  • beautifulsoup4:解析HTML
  • fake-useragent:生成随机User-Agent(反爬必备)

2. 基础请求代码

python 复制代码
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent

def 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.text
    except 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结构:

xml 复制代码
<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. 完整解析代码

复制代码
ini 复制代码
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)

输出示例

css 复制代码
{'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)去除空白字符
  • 结构化输出:将每行数据转为字典,便于后续处理

四、完整采集流程

将上述代码整合为完整脚本,并添加数据存储功能:

python 复制代码
import csv
from datetime import datetime

def 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参数实现:

csharp 复制代码
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点自动采集:

scss 复制代码
import schedule
import time

def job():
    print("开始定时采集...")
    main()

schedule.every().day.at("08:00").do(job)

while True:
    schedule.run_pending()
    time.sleep(60)

3. 数据可视化

用Matplotlib简单绘制温度变化曲线:

scss 复制代码
import matplotlib.pyplot as plt

def 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策略。更简单的方案是设置请求间隔:

python 复制代码
import time
import random

def safe_request(url):
    time.sleep(random.uniform(1, 3))  # 随机延迟1-3秒
    return get_weather_page(url)
复制代码
Q2:网站结构变了怎么办?

A:定期检查解析代码是否还能正常工作。建议:

  1. 将选择器(如class_='twoInner')提取为配置变量
  2. 添加页面结构校验逻辑
  3. 使用try-except捕获解析异常

Q3:如何采集动态加载的数据?

A:对于JavaScript渲染的数据,有两种方案:

  1. 分析接口:用浏览器开发者工具查找数据API(推荐)
  2. Selenium模拟:对复杂页面可使用Selenium+WebDriver

Q4:采集频率应该设置多少?

A:遵循robots.txt协议和网站服务条款。一般建议:

  • 公开数据:每小时不超过1次
  • 商业数据:联系网站获取授权
  • 添加随机延迟避免规律性请求

Q5:如何存储大量历史数据?

A:根据数据量选择:

  • 小规模:CSV/Excel
  • 中等规模:SQLite数据库
  • 大规模:MySQL/MongoDB等专业数据库

七、总结与展望

通过本文,你已掌握:

  1. 使用Requests发送HTTP请求
  2. 用BeautifulSoup解析HTML
  3. 提取结构化天气数据
  4. 存储和可视化数据
  5. 常见问题的解决方案

实际应用中,你可能需要处理:

  • 登录验证
  • 验证码识别
  • 分布式采集
  • 数据去重

建议从简单需求开始,逐步添加复杂功能。记住:爬虫开发的核心是模拟人类浏览行为,保持请求的随机性和合理性是长期运行的关键。

相关推荐
Rhys..2 小时前
Gerkin+Pytest(python)实现自动化(BDD)
python·自动化·pytest
大佐不会说日语~2 小时前
若依框架 (Spring Boot 3) 集成 knife4j 实现 OpenAPI 文档增强
spring boot·后端·python
MATLAB代码顾问2 小时前
Python实现手榴弹爆炸算法(Grenade Explosion Method, GEM)(附完整代码)
开发语言·python·算法
困鲲鲲2 小时前
NumPy 系列(六):numpy 数组函数
python·numpy
人工干智能2 小时前
Python的大杀器:Jupyter Notebook处理.ipynb文件
开发语言·python·jupyter
跳跳的向阳花3 小时前
02、Python从入门到癫狂:函数与数据容器
开发语言·python
这里有鱼汤3 小时前
如何用Python找到股票的支撑位和压力位?——均线簇
后端·python
啃啃大瓜3 小时前
字符串
python
啊森要自信4 小时前
【 GUI自动化测试】GUI自动化测试(一) 环境安装与测试
开发语言·python·ui·单元测试·pytest