首页 > 其他分享 >爬虫案例-2345天气王历史天气获取

爬虫案例-2345天气王历史天气获取

时间:2024-11-12 21:19:09浏览次数:3  
标签:2345 return 请求 df 天气 爬虫 year table 数据

爬虫案例-2345天气王历史天气获取

1. 项目简介

本项目的目的是利用网络爬虫技术,在2345天气王网站中,获取重庆从2011年至2023年的历史天气数据,包括每日温度、降雨量等信息。通过数据的获取与清洗,我们能够更好地研究重庆的气候变化趋势,为相关分析提供基础数据支持。

2. 进入网站并初步分析

2.1 访问网站

访问目标网站(2345天气王),找到重庆历史天气页面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 页面结构分析

使用浏览器的开发者工具(通常可以通过按 F12 键打开)来分析页面结构。重点观察页面上展示历史天气数据的部分,确定其展示形式。常见的展示形式包括:

  • 表格:历史天气数据可能以表格的形式展现,每行或每列对应不同日期的天气信息,如温度、降雨量等。
  • 文本块:部分数据可能以段落或分散的文本块形式存在,需要通过爬虫代码解析具体标签内容。
  • 图表:如果有数据可视化图表,可能需要进一步确认是否存在隐藏数据源或通过额外请求获取。

在这里插入图片描述

通过分析可知,历史天气数据以表格形式展示,对应HTML标签为<table class="history-table">

2.3 数据加载方式判断

在分析过程中,需要判断页面数据是否通过JavaScript动态加载。

(1)如果是动态加载的数据,则通常需要使用抓包工具来分析数据请求的API地址和参数。通过观察网络请求(Network 请求)面板中的XHR请求,可以获取数据来源的接口地址及其请求头信息,为后续的抓包步骤提供帮助。

(2)如果数据是静态页面加载的,则可以直接使用爬虫解析HTML来获取目标数据。

在这里插入图片描述

例如,选择2024年10月时,可以在控制台的网络请求中发现XHR请求,点击查看传参内容。

3. 代码实现步骤

3.1 模拟访问和数据抓取

首先,我们使用requests库模拟对目标网页的访问,并通过伪装HTTP请求头来模拟真实用户的访问行为,以避免触发反爬虫机制。

import requests 
import random

# 模拟多个 User-Agent 以模拟不同的浏览器访问
# 这里定义了一个包含常见浏览器标识的列表,用于伪装成不同的浏览器访问网站
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0',
    # 其他 User-Agent 字符串可以继续添加以模拟更多浏览器
    ...
]

# 获取随机 User-Agent 头部信息的函数
# 该函数随机从 user_agents 列表中选择一个 User-Agent 字符串,并构造一个请求头部
def get_random_headers():
    return {
        'User-Agent': random.choice(user_agents),  # 随机选择一个 User-Agent 字符串
        'Accept': 'application/json, text/javascript, */*; q=0.01',  # 设置请求头部的 Accept 字段,指定期望接受的响应类型
        'Referer': 'https://tianqi.2345.com/wea_history/57516.htm',  # 设置请求头部的 Referer 字段,伪装请求来源页面
    }

3.2 URL构建与请求发送

我们构建请求URL和参数,用于指定获取的年份和月份,并通过发送HTTP请求获取响应数据。

def build_request_params(year, month):
    # 构建请求的 URL 和参数
    url = "https://tianqi.2345.com/Pc/GetHistory"  # 目标网站的历史天气数据接口
    params = {
        'areaInfo[areaId]': 57516,  # 重庆市的地区 ID,用于获取指定地区的数据
        'areaInfo[areaType]': 2,  # 地区类型,1 表示国外城市,2 表示国内城市
        'date[year]': year,  # 查询的年份
        'date[month]': month,  # 查询的月份
    }
    return url, params  # 返回构建好的 URL 和参数
def fetch_weather_data(url, params):
    # 获取天气数据
    headers = get_random_headers()  # 使用随机的请求头部信息以模拟不同浏览器
    response = requests.get(url, headers=headers, params=params)  # 发送 HTTP GET 请求
    if response.status_code == 200:  # 判断请求是否成功(状态码 200 表示成功)
        return response.json()  # 如果请求成功,则返回 JSON 格式的数据
    else:
        # 请求失败时,打印状态码并返回 None
        print(f"请求失败,状态码: {response.status_code}")
        return None

3.3 数据解析和处理

我们使用BeautifulSoup解析HTML数据,并将其转换为pandasDataFrame格式,便于数据操作和清洗。

from bs4 import BeautifulSoup  # 导入 BeautifulSoup 库用于解析 HTML
import pandas as pd  # 导入 Pandas 库用于数据操作

def parse_html_to_dataframe(html_string):
    # 将 HTML 字符串解析为数据框
    soup = BeautifulSoup(html_string, 'html.parser')  # 使用 BeautifulSoup 解析 HTML 字符串
    table = soup.find('table', class_='history-table')  # 查找包含历史数据的表格元素
    if table:  # 如果找到表格
        table_str = str(table)  # 将表格转为字符串
        df = pd.read_html(StringIO(table_str))[0]  # 使用 Pandas 读取表格数据并转换为 DataFrame
        return df  # 返回 DataFrame
    else:
        print("未找到表格数据")  # 如果未找到表格,输出提示信息
        return None  # 返回 None

3.4 数据合并与保存

在循环爬取每年的每月数据时,我们逐步将数据合并,并最终保存到CSV文件中。

def merge_dataframes(final_df, new_df):
    # 合并数据框的函数
    # 如果 new_df 不为 None,则将其与 final_df 合并
    if new_df is not None:
        return pd.concat([final_df, new_df], ignore_index=True)  # 使用 pd.concat 进行合并,并重置索引
    return final_df  # 如果 new_df 为空,返回原来的 final_df

# 将最终的数据框保存为 CSV 文件
final_df.to_csv('weather_data.csv', index=False)  # 保存数据到 'weather_data.csv' 文件,不保留索引列

3.5 爬虫优化

为了避免频繁请求被检测,我们模拟了人类访问的行为,随机延迟请求时间。同时,我们设置了多种User-Agent来防止被识别为爬虫请求。

import time  # 导入 time 模块用于延时功能

def simulate_human_behavior(min_delay=0.5, max_delay=3.5):
    """
    模拟人类行为的函数,主要通过延时来模仿人类浏览网页的时间间隔,以避免被目标网站识别为爬虫程序。
    
    参数:
    min_delay (float): 最小延时(单位为秒),默认为 0.5 秒
    max_delay (float): 最大延时(单位为秒),默认为 3.5 秒
    """
    # 在 min_delay 和 max_delay 之间随机生成一个延时,并暂停程序运行
    time.sleep(random.uniform(min_delay, max_delay))

4. 完整代码

# 导入必要的库
import requests
import pandas as pd
from io import StringIO  # 用于将 HTML 转换为可读的字符串流
from bs4 import BeautifulSoup  # 用于解析 HTML 内容
import itertools  # 用于生成年份和月份的组合
import time  # 用于引入时间延迟
import random  # 用于生成随机数模拟不同的请求头和延迟

# 准备多个 User-Agent 模拟不同的浏览器,防止爬虫被检测
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1'
]

# 获取随机 User-Agent 的请求头,模拟不同的浏览器请求
def get_random_headers():
    return {
        'User-Agent': random.choice(user_agents),  # 随机选择一个 User-Agent
        'Accept': 'application/json, text/javascript, */*; q=0.01',  # 接受的返回数据类型
        'Accept-Encoding': 'gzip, deflate, br, zstd',  # 压缩编码
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',  # 支持的语言
        'X-Requested-With': 'XMLHttpRequest',  # 表示通过 Ajax 发出的请求
        'Connection': 'keep-alive',  # 保持连接
        'Referer': 'https://tianqi.2345.com/wea_history/57516.htm',  # 来源网址,用于表明请求的来源页面
        'Origin': 'https://tianqi.2345.com'  # 请求来源,防止跨域请求问题
    }

# 构建请求 URL 和参数,用于指定具体年份和月份的天气数据
def build_request_params(year, month):
    url = "https://tianqi.2345.com/Pc/GetHistory"  # 请求的基础 URL
    params = {
        'areaInfo[areaId]': 57516,  # 地区 ID,代表重庆市
        'areaInfo[areaType]': 2,  # 地区类型,2 代表城市
        'date[year]': year,  # 请求的年份
        'date[month]': month,  # 请求的月份
    }
    return url, params  # 返回 URL 和请求参数

# 发送请求并获取响应数据,检查状态码,确保请求成功
def fetch_weather_data(url, params):
    headers = get_random_headers()  # 获取随机请求头
    response = requests.get(url, headers=headers, params=params)  # 发送 GET 请求
    if response.status_code == 200:  # 检查是否成功响应
        return response.json()  # 返回响应数据(JSON 格式)
    else:
        print(f"请求失败,状态码: {response.status_code}")  # 输出错误信息
        return None  # 请求失败时返回 None

# 解析 HTML 数据并将其转换为 Pandas DataFrame 以便后续数据处理
def parse_html_to_dataframe(html_string):
    soup = BeautifulSoup(html_string, 'html.parser')  # 使用 BeautifulSoup 解析 HTML
    table = soup.find('table', class_='history-table')  # 查找具有特定 class 的表格
    
    if table:  # 如果找到表格
        table_str = str(table)  # 将表格转换为字符串形式
        table_io = StringIO(table_str)  # 使用 StringIO 将其转换为可读的字符串流
        df = pd.read_html(table_io)[0]  # 使用 pandas 读取 HTML 表格,转换为 DataFrame
        return df  # 返回 DataFrame
    else:
        print("未找到表格数据")  # 如果未找到表格,输出提示信息
        return None  # 返回 None

# 将新的 DataFrame 与之前的数据合并
def merge_dataframes(final_df, new_df):
    if new_df is not None:  # 如果新数据存在
        return pd.concat([final_df, new_df], ignore_index=True)  # 合并 DataFrame 并重置索引
    return final_df  # 如果没有新数据,则返回原始的 final_df

# 模拟人类行为,随机延迟一定时间,防止请求过于频繁
def simulate_human_behavior(min_delay=0.5, max_delay=3.5):
    time.sleep(random.uniform(min_delay, max_delay))  # 随机延迟 0.5 到 3.5 秒

# 显示当前爬取进度,年份和月份的进度显示
def display_progress(year, month, current_year):
    if year == current_year:  # 如果当前年份与上次相同
        print('\t#', end='')  # 输出进度标识,不换行
    else:
        print(f'\n{year}年\t#', end='')  # 输出年份并换行,表示新的年份开始
    return year  # 返回当前年份

# 主函数,负责执行天气数据的爬取任务
def main():
    
    print('重庆市2011-2023年历史天气数据爬取开始:')
    print('-' * 100)  # 打印分割线,表示爬取开始
    
    # 初始化空 DataFrame,用于存储爬取到的所有数据
    final_df = pd.DataFrame()

    # 定义年份和月份的范围
    years = range(2011, 2024)  # 从 2011 年到 2023 年
    months = range(1, 13)  # 1 月到 12 月
    year_month_combinations = itertools.product(years, months)  # 生成所有年份和月份的组合

    # 输出月份表头
    header = '\t' + '\t'.join([f'{x}月' for x in months])  # 生成月份表头字符串
    print(header, end='')  # 输出月份表头
    
    # 跟踪当前年份,初始化为 0
    current_year = 0

    # 遍历所有年份和月份
    for year, month in year_month_combinations:
        # 构建请求的 URL 和参数
        url, params = build_request_params(year, month)

        # 模拟人类行为,避免频繁请求,实际使用时可以启用这行代码
        simulate_human_behavior()

        # 获取天气数据
        response_data = fetch_weather_data(url, params)  # 获取 JSON 响应
        if response_data:
            html_string = response_data.get('data', '')  # 提取 HTML 数据
            
            # 解析 HTML 并转换为 DataFrame
            new_df = parse_html_to_dataframe(html_string)

            # 合并新数据到最终 DataFrame
            final_df = merge_dataframes(final_df, new_df)

            # 更新并显示进度
            current_year = display_progress(year, month, current_year)

    # 最终输出爬取完成信息
    print('\n' + '-' * 100, end='')  # 打印分割线,表示爬取结束
    print("\n数据爬取完成。")  # 输出提示信息
    return final_df  # 返回最终的 DataFrame

# 调用主函数
if __name__ == "__main__":
    
    result_df = main()  # 执行爬取任务
    
    result_df.to_csv('weather_data.csv', index=False)  # 保存数据到 CSV 文件

在这里插入图片描述
在这里插入图片描述

5. 总结

本项目通过爬虫获取历史天气数据,利用数据分析工具进行清洗和合并,为重庆气候趋势分析提供了可靠的数据支持。通过优化爬虫策略和代码结构,提高了爬取效率和稳定性。

标签:2345,return,请求,df,天气,爬虫,year,table,数据
From: https://blog.csdn.net/MoRanzhi1203/article/details/143721939

相关文章

  • 程序员必备的几款爬虫软件,搞定复杂数据抓取任务
    作为一名数据工程师,三天两头要采集数据,用过十几种爬虫软件,也用过Python爬虫库,还是建议新手使用现成的软件比较方便。这里推荐3款不错的自动化爬虫工具,八爪鱼、亮数据、WebScraper1.八爪鱼爬虫八爪鱼爬虫是一款功能强大的桌面端爬虫软件,主打可视化操作,即使是没有任何编......
  • 猿人学web端爬虫攻防大赛赛题第5题——js 混淆 - 乱码增强
    题目网址:https://match.yuanrenxue.cn/match/5解题步骤抓数据包。在请求头和请求体中都有加密的内容。比较特殊的就RM4hZBv0dDon443M字段,全局搜索一下。没有任何内容,只能跟第2题一样,利用fiddler来设置断点了。(function(){'usestrict';varcookieTemp=''......
  • 使用 Python 实现高效网页爬虫——从获取链接到数据保存
    前言在这个时代,网络爬虫已成为数据分析与信息收集不可或缺的技术之一。本文将通过一个具体的Python项目来介绍如何构建一个简单的网络爬虫,它能够自动抓取指定网站的文章链接、标题、正文内容以及图片链接,并将这些信息保存为CSV文件。目标网站一、准备工作在开始编写爬......
  • 双十一购物攻略:如何利用爬虫技术获取历史价格趋势,理性购物不踩雷
    双十一购物狂欢节即将到来,作为程序员,利用爬虫技术查询商品的历史价格趋势,似乎是一个合理的需求,毕竟这只是为了自己参考,不涉及商业用途。然而,小伙伴们在进行爬虫操作时一定要谨慎小心,尤其是在数据采集和使用的过程中,务必遵守相关法律法规与平台的使用规范。每次和大家讲解爬虫时,我......
  • # Playwright爬虫(.net)介绍:1 简介
    Playwright是一个由Microsoft开发的开源工具,用于自动化Web浏览器的测试和操作。它提供了一种跨浏览器、跨平台的自动化解决方案,可以在Chromium、FireFox、微软Edge等多种浏览器上进行测试和操作。如果你曾经使用过Selenium,那么我可以告诉你,Playwright的用途与Selenium非常类似,可......
  • Playwright爬虫(.net)介绍:2 安装及第一个应用程序
    Playwright的安装比较简单,只需要使用命令行输入几行命令就可以完成。由于本系统主要通过MicrosoftVisualStudioCommunity2022及C#进行记录,因此在安装Playwright前需要自行完成相关开发环境的搭建。1.运行PowerShell,并定位到某个目录中。2.输入如下命令,新建一个mstest项目:do......
  • PHP爬虫:精准获取京东商品SKU信息
    在电商领域,商品的SKU(StockKeepingUnit)信息至关重要,它不仅是库存管理的基础,也是数据分析的关键。京东作为中国最大的电商平台之一,拥有海量的商品数据。本文将介绍如何使用PHP编写爬虫,精准获取京东商品的SKU信息。1.了解京东商品页面结构在编写爬虫之前,我们需要了解京东商品......
  • Java爬虫:京东商品SKU信息的“偷心盗贼”
    在这个信息爆炸的时代,数据就像是藏在深山里的宝藏,等待着我们这些“数据探险家”去发掘。今天,我们要化身为一名“偷心盗贼”,用Java这把锋利的“剑”,精准地从京东的海洋中窃取商品的SKU信息。别担心,我们这是合法的“盗窃”,因为我们只是在学习如何用代码与网页对话。环境准备:装......
  • Java爬虫精准获得JD商品SKU信息
    在数字化时代,数据的价值日益凸显,尤其是在电商领域。通过爬虫技术,我们可以从网站中提取有价值的信息,用于市场分析、价格监控等。Java作为一种成熟且功能强大的编程语言,拥有丰富的库支持,使其成为编写爬虫的理想选择。本文将详细介绍如何使用Java编写爬虫,以精准获取京东(JD)商品的详......
  • PHP爬虫:京东商品详情的“偷窥”大法
    大家好,今天我们要聊的是如何用PHP做一个“偷窥狂”,哦不,是一个优雅的数据收集者,去获取京东商品的详情。放心,我们的目标是光明正大的,我们只是想要那些公开的数据,不会去触碰任何不该触碰的东西。1.预备,开始你的表演在开始之前,我们需要准备一些道具。首先,你需要一个PHP环境,就像......