从网络爬虫到数据清洗:重庆天气数据采集与质量分析实战
发布时间:2026/9/3 14:28:09来源:尧图网络
简介本资源是一份面向计算机、电子信息工程及数学等专业本科生的机器学习综合实践项目聚焦重庆地区天气数据采集与空气质量分析覆盖爬虫开发、数据清洗、特征工程到基础预测建模全流程适用于课程设计、期末大作业及毕业设计等中阶实践场景。压缩包共6个文件3个Excel数据表用于存储爬取的天气与空气质量原始/合并数据3个Python脚本分别实现网页爬取、数据读取与简单预测功能整体体积仅369KB轻量易部署。已有367人下载学习代码采用参数化设计关键步骤均含中文注释运行逻辑清晰且经实测可直接执行配套文档说明完整覆盖环境配置、参数调整方法与结果解读便于快速复现与二次开发。1. 项目概述从数据采集到智能分析的完整闭环最近在带学生做机器学习相关的课程设计发现一个普遍现象很多同学把“机器学习”等同于“调包调参”却忽略了最基础也最关键的一环——数据从哪里来质量又如何保证。一个典型的作业需求是“分析重庆天气”。这看似简单背后却串联起数据工程与机器学习应用的完整链路。这个项目正是以“重庆天气”为靶心构建一个从网络爬虫实时抓取到数据清洗与质量评估再到初步分析与可视化的端到端实践案例。它不仅仅是一个爬虫脚本更是一个微型的、可复现的数据科学项目模板。对于初学者而言最大的价值在于能亲手触摸数据生产的全过程。你将从零开始编写爬虫从权威气象网站获取重庆的温湿度、空气质量AQI、风向风速等原始数据然后你会面对真实数据中必然存在的缺失值、异常值和格式混乱问题并学习如何用Pandas等工具“收拾干净”最后你将运用基础的统计方法和可视化库对清洗后的数据进行探索性分析形成对重庆天气特征的直观认知。整个过程所需的全部材料——可运行的Python源代码、详尽的步骤文档、处理后的示例数据集——都已打包完备。无论你是想完成一门课程作业还是希望夯实数据获取与预处理这项数据科学家的核心基本功这个项目都能提供一个结构清晰、可直接上手的实战沙盒。2. 项目核心设计思路与架构拆解2.1 为什么选择“天气数据”作为分析对象天气数据是数据科学入门近乎完美的练手对象。首先它数据源稳定且公开国内外有众多气象网站如中国天气网、Weather.com等提供结构化或半结构化的数据爬取难度适中既涉及HTTP请求、HTML解析又不会因反爬机制过于复杂而劝退新手。其次数据维度丰富包含数值型温度、气压、类别型天气现象、风向、时序型按小时/天更新能覆盖大部分基础的数据处理场景。最后它具备天然的时空属性和业务关联性便于延展出有意义的分析问题比如空气质量与季节的关系、温度趋势预测等为后续引入机器学习模型提供了自然的切入点。选择重庆作为具体分析城市则增加了项目的典型性。重庆地形特殊被称为“山城”其天气数据可能呈现出与平原城市不同的特征如局部小气候明显、湿度常年较高等。分析这样的数据能让你更深刻地理解“数据背景”的重要性——同样的分析方法作用于不同特征的数据集结果和解读可能截然不同。2.2 整体技术栈与流程设计本项目采用经典的Python数据科学技术栈遵循“数据采集 - 数据存储 - 数据清洗 - 数据分析 - 结果呈现”的流水线。整个架构可以清晰地分为三个层次数据采集层核心工具是requests库用于发送网络请求以及BeautifulSoup或lxml用于解析HTML页面提取所需的天气数据。这一层的目标是稳定、准确地将目标网页上的非结构化信息转化为结构化的数据如JSON、CSV格式。数据处理与分析层这是项目的重心。我们将使用pandas作为数据操作的瑞士军刀进行数据加载、清洗、转换和聚合。numpy提供底层的数值计算支持。对于数据质量分析我们会计算基本的统计量均值、标准差、缺失率并通过规则如3σ原则或业务逻辑如温度不可能高于60℃来识别异常值。初步的分析可能涉及简单的趋势计算和相关性观察。数据可视化与输出层使用matplotlib和seaborn库生成图表将数据模式直观展现。同时利用Jupyter Notebook或编写规范的Python脚本将整个分析过程包括代码、图表和文字说明整合成可交互或可执行的文档实现真正的“源代码文档”一体化。注意在设计爬虫时务必遵守目标网站的robots.txt协议并采取礼貌的爬取策略例如在请求间添加随机延时使用time.sleep避免对目标服务器造成压力这是基本的网络道德和规避反爬虫机制的必要措施。2.3 工具选型背后的考量你可能会有疑问为什么用BeautifulSoup而不是Scrapy为什么用pandas而不用直接操作numpy数组对于爬虫部分Scrapy无疑是功能更强大的工业级框架但其学习曲线相对陡峭且对于目标明确、页面结构相对简单的天气数据抓取任务来说显得有些“杀鸡用牛刀”。requestsBeautifulSoup的组合更加轻量、直观适合初学者快速理解HTTP请求和HTML解析的基本原理将注意力集中在数据提取逻辑本身。对于数据处理pandas的DataFrame结构是处理表格型数据的“事实标准”。它封装了numpy的高性能并提供了极其丰富且便捷的数据操作接口如分组、透视、合并。直接使用numpy需要编写大量循环和索引代码而pandas的一行命令往往就能解决能极大提升开发效率和代码可读性。在数据质量分析中pandas的.describe()、.isnull().sum()等方法可以瞬间给出数据的全局画像。3. 核心模块一重庆天气数据爬虫实现详解3.1 目标网站分析与请求构造实现爬虫的第一步是“侦察”。我们需要手动打开目标天气网站例如以中国天气网重庆页面为例使用浏览器的开发者工具F12来观察网络请求和数据呈现方式。关键步骤定位数据源查看页面是静态加载还是动态渲染。对于天气数据很多网站会直接嵌入在HTML中。在“元素”Elements面板搜索“温度”、“湿度”等关键词找到包裹这些数据的HTML标签及其CSS选择器路径。例如可能发现当前温度在一个p classtem的标签里。分析请求在“网络”Network面板刷新页面观察加载了哪些请求。重点关注XHR/Fetch请求有时数据会通过API接口返回格式多为JSON这比解析HTML更简单。如果找到这样的API爬取效率和质量会高很多。构造请求头复制其中一个重要请求的Request Headers特别是User-Agent将其伪装成真实浏览器访问是绕过基础反爬的第一步。我们可以在代码中构建一个这样的字典headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 }3.2 使用Requests与BeautifulSoup解析数据假设我们确定数据在静态HTML中接下来就是编写抓取与解析代码。基础抓取流程import requests from bs4 import BeautifulSoup import pandas as pd import time def fetch_weather_data(url): 抓取指定URL的天气数据 try: # 发送GET请求带上请求头 response requests.get(url, headersheaders, timeout10) response.raise_for_status() # 检查请求是否成功 response.encoding response.apparent_encoding # 自动识别编码 return response.text except requests.RequestException as e: print(f请求失败: {e}) return None def parse_weather_html(html): 解析HTML提取天气信息 if not html: return {} soup BeautifulSoup(html, html.parser) weather_info {} # 示例根据实际页面结构调整选择器 # 假设温度在class为temp的span标签内 temp_tag soup.find(span, class_temp) weather_info[temperature] temp_tag.get_text(stripTrue) if temp_tag else None # 假设湿度在某个div中 humidity_tag soup.find(div, textre.compile(湿度)) # 更稳健的方法是找到包含“湿度”的标签然后取相邻的数值标签 # ... 更多字段的解析逻辑 return weather_info实操心得选择器的稳健性不要依赖过于复杂或容易变化的CSS路径。优先使用find和find_all结合标签名和相对稳定的属性如class。有时结合正则表达式re模块来匹配文本模式会更灵活。异常处理网络请求和页面解析随时可能出错。务必用try...except包裹关键代码并对每个提取的字段都做if tag:的判断避免因某个标签缺失导致整个程序崩溃。数据标准化提取出来的文本往往带有单位如“12℃”、“湿度 78%”需要在解析时或后续清洗阶段使用字符串方法.strip(),.replace()或正则表达式将其转换为纯数值方便后续计算。3.3 实现多日历史数据抓取与存储单次抓取只能获得当前或未来几天的数据。对于天气质量分析我们更需要历史数据。这就需要设计一个循环爬取逻辑。策略设计分析URL规律观察历史数据页面的URL是否遵循某种模式例如http://xxx.weather.com.cn/weather/101040100_20240520.shtml其中最后一部分是日期。如果是通过API则查看请求参数中是否包含date字段。构造日期序列使用Python的datetime模块生成需要抓取的一系列日期字符串。循环抓取与延时遍历日期序列构造完整URL并发起请求。在每次请求后务必使用time.sleep(random.uniform(1, 3))添加随机延时模拟人类操作这是维持爬虫长期稳定运行的关键。增量式存储每成功抓取并解析完一天的数据就立即将其追加存储到本地文件如CSV或数据库中。这样做的好处是即使中途程序因网络等原因中断已抓取的数据也不会丢失。下次运行时可以先检查本地已有哪些日期的数据只抓取缺失的部分。存储示例import csv from datetime import datetime, timedelta def save_to_csv(data, filenamechongqing_weather.csv): 将数据字典保存或追加到CSV文件 file_exists os.path.isfile(filename) with open(filename, a, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesdata.keys()) if not file_exists: writer.writeheader() # 文件不存在时写入表头 writer.writerow(data) # 在主循环中 start_date datetime(2023, 1, 1) end_date datetime(2023, 12, 31) current_date start_date while current_date end_date: date_str current_date.strftime(%Y%m%d) url fhttp://目标网站/路径/{date_str}.html html fetch_weather_data(url) if html: daily_data parse_weather_html(html) daily_data[date] date_str # 加入日期字段 save_to_csv(daily_data) print(f成功抓取 {date_str} 数据) time.sleep(random.uniform(2, 5)) # 重要随机延时 current_date timedelta(days1)4. 核心模块二数据清洗与质量评估实战抓取到的原始数据通常是“脏”的。直接用于分析会导致结果失真。数据清洗的目标是将其转化为高质量、一致化的数据集。4.1 数据加载与初步探查使用pandas加载我们抓取的CSV文件并进行第一次“体检”。import pandas as pd import numpy as np # 加载数据 df pd.read_csv(chongqing_weather.csv, parse_dates[date]) # 将日期列解析为datetime类型 # 查看数据概览 print(数据形状行列:, df.shape) print(\n前5行数据:) print(df.head()) print(\n数据基本信息:) print(df.info()) print(\n数值型字段的描述性统计:) print(df.describe())df.info()会告诉我们每列的非空值数量从而快速定位缺失情况。df.describe()则展示数值列的统计特征如均值、标准差、最小最大值有助于发现异常值的苗头。4.2 处理缺失值与异常值缺失值处理缺失值产生的原因很多可能是爬虫解析失败、网站当天未更新等。处理方式需根据业务逻辑和数据量决定。删除如果某一行缺失了关键字段如温度或者缺失数据比例很高可以考虑删除该行。使用df.dropna(subset[temperature], inplaceTrue)。填充对于时间序列数据常用前后相邻时刻的值来填充前向填充或后向填充。df[column].fillna(methodffill, inplaceTrue)。也可以使用该字段的均值、中位数进行填充但这可能会平滑掉一些真实波动。异常值检测与处理异常值可能是真实的极端天气也可能是爬虫或解析错误。需要结合业务知识判断。统计方法对于近似正态分布的数据可以使用“3σ原则”即认为超过均值上下3个标准差范围的值是异常值。mean_val df[temperature].mean() std_val df[temperature].std() lower_bound mean_val - 3 * std_val upper_bound mean_val 3 * std_val outliers df[(df[temperature] lower_bound) | (df[temperature] upper_bound)]业务规则法根据常识设定合理范围。例如重庆的室外温度历史记录在-5℃到45℃之间那么超出这个范围的值极有可能是错误的可以将其视为缺失值并进行处理。df.loc[df[temperature] 45, temperature] np.nan df.loc[df[temperature] -5, temperature] np.nan处理完异常值后可以再用填充缺失值的方法来处理这些被标记为NaN的数据。注意处理异常值时切忌不假思索地直接删除。尤其是对于时间序列删除一个点可能会破坏连续性。更好的做法是先标记然后分析其产生原因再决定是修正、填充还是删除。在文档中记录下所有清洗操作及其理由是专业的数据分析习惯。4.3 数据格式标准化与特征工程清洗后的数据还需要统一格式并可能衍生出新的特征以供分析。格式统一确保日期格式一致、数值列都是数字类型df[column] pd.to_numeric(df[column], errorscoerce)、文本类数据如天气状况“晴”、“多云”的取值是有限的、一致的。特征工程这是为后续分析特别是机器学习做准备。例如从日期中提取“月份”、“季节”、“是否周末”等时序特征。计算温差日最高温与最低温之差。将风向的文本描述如“东北风”转换为角度或进行分类编码。根据AQI数值生成空气质量等级标签优、良、轻度污染等。# 示例从日期创建新特征 df[month] df[date].dt.month df[season] df[month].apply(lambda x: 1 if x in [12,1,2] else (2 if x in [3,4,5] else (3 if x in [6,7,8] else 4))) # 冬春夏秋 df[day_of_week] df[date].dt.dayofweek # 周一为0 df[is_weekend] df[day_of_week].apply(lambda x: 1 if x 5 else 0)5. 核心模块三重庆天气数据探索性分析数据清洗完毕后我们就可以开始“阅读”数据了。探索性数据分析EDA不涉及复杂的模型而是通过统计和可视化来理解数据的基本特征、分布和关系。5.1 单变量分布分析了解每个关键指标的分布情况。例如重庆全年的温度分布如何空气质量指数主要集中在哪个区间import matplotlib.pyplot as plt import seaborn as sns plt.style.use(seaborn-v0_8-darkgrid) # 设置一个好看的样式 # 绘制温度分布直方图与核密度估计 plt.figure(figsize(10, 6)) sns.histplot(df[temperature], kdeTrue, bins30) plt.title(重庆全年温度分布) plt.xlabel(温度 (℃)) plt.ylabel(频次) plt.show() # 绘制空气质量等级饼图 aqi_level_counts df[aqi_level].value_counts() # 假设已生成aqi_level列 plt.figure(figsize(8,8)) plt.pie(aqi_level_counts.values, labelsaqi_level_counts.index, autopct%1.1f%%, startangle90) plt.title(重庆空气质量等级分布) plt.show()通过单变量分析我们可以得到诸如“重庆年平均温度约为18℃”、“空气质量以‘良’为主”等基础结论。5.2 时间序列趋势分析天气数据是典型的时间序列。观察其随时间变化的趋势、周期性和异常点至关重要。# 绘制月度平均温度变化折线图 monthly_avg_temp df.groupby(month)[temperature].mean() plt.figure(figsize(12, 6)) monthly_avg_temp.plot(markero) plt.title(重庆月平均温度变化2023年) plt.xlabel(月份) plt.ylabel(平均温度 (℃)) plt.grid(True) plt.xticks(range(1,13)) plt.show() # 绘制全年每日AQI走势图 plt.figure(figsize(15, 5)) plt.plot(df[date], df[AQI], linewidth0.5) plt.title(重庆2023年AQI每日变化) plt.xlabel(日期) plt.ylabel(AQI) plt.xticks(rotation45) plt.tight_layout() plt.show()从趋势图中我们可以清晰地看到重庆夏季高温、冬季湿冷的特点以及AQI在冬季可能因扩散条件差而升高的现象。5.3 多变量关系分析探索不同天气要素之间的相关性。例如温度和湿度是否负相关风速对空气质量改善是否有积极作用# 计算数值型字段间的相关系数矩阵 numeric_cols [temperature, humidity, wind_speed, AQI, pressure] corr_matrix df[numeric_cols].corr() print(相关系数矩阵) print(corr_matrix) # 绘制相关系数热力图 plt.figure(figsize(8, 6)) sns.heatmap(corr_matrix, annotTrue, cmapcoolwarm, center0, squareTrue) plt.title(天气要素相关系数热力图) plt.tight_layout() plt.show() # 绘制温度与AQI的散点图 plt.figure(figsize(10, 6)) plt.scatter(df[temperature], df[AQI], alpha0.5, s10) plt.title(温度与AQI关系散点图) plt.xlabel(温度 (℃)) plt.ylabel(AQI) plt.grid(True) plt.show()热力图能直观展示变量间的线性关系强度。散点图则能帮助发现非线性关系或异常集群。例如你可能会发现在某个温度区间内AQI值分布特别集中或分散。6. 项目文档编写与代码组织规范一个可交付的作业或项目清晰的文档和规范的代码结构与代码本身同样重要。6.1 源代码组织结构建议按功能模块组织代码文件而不是把所有代码堆在一个脚本里。一个良好的结构示例如下chongqing_weather_analysis/ │ ├── src/ # 源代码目录 │ ├── crawler.py # 爬虫模块包含请求、解析函数 │ ├── data_cleaner.py # 数据清洗模块 │ ├── analyzer.py # 数据分析与可视化模块 │ └── main.py # 主程序入口调度各个模块 │ ├── data/ # 数据目录 │ ├── raw/ # 原始爬取数据 │ └── processed/ # 清洗后的数据 │ ├── output/ # 输出目录 │ ├── figures/ # 生成的图表 │ └── report/ # 分析报告 │ ├── config.py # 配置文件如URL、请求头、数据库连接信息 ├── requirements.txt # 项目依赖包列表 └── README.md # 项目总说明文档在main.py中你可以清晰地展示整个工作流# main.py from src.crawler import fetch_historical_weather from src.data_cleaner import load_and_clean_data from src.analyzer import perform_eda, generate_report def main(): print(步骤1: 抓取数据如果本地没有...) # fetch_historical_weather(start_date, end_date) print(步骤2: 加载并清洗数据...) df_clean load_and_clean_data(data/raw/weather.csv) print(步骤3: 进行探索性分析并生成图表...) perform_eda(df_clean) generate_report(df_clean) print(分析完成结果已保存至 output/ 目录。) if __name__ __main__: main()6.2 撰写高质量的README与文档说明README.md是项目的门面应该包含以下部分项目标题与简介一句话说明项目是做什么的。主要功能用列表形式列出核心功能点如支持抓取XX网站重庆历史天气、提供数据清洗流程、包含基础数据分析与可视化。快速开始环境要求Python 3.8。安装依赖pip install -r requirements.txt。运行步骤如何配置如果需要如何运行主程序python main.py。文件结构说明简要说明项目目录树如上文所示。数据字段说明提供一个表格描述清洗后数据集中每个字段的名称、含义、数据类型和示例。字段名说明类型示例date观测日期datetime2023-01-01temperature平均温度℃float12.5AQI空气质量指数int65weather天气现象str多云注意事项声明数据来源、爬虫使用规范如遵守robots.txt、设置延时、以及可能的数据局限性。后续扩展方向可以建议如何在此基础上增加机器学习预测模型、更复杂的可视化等。此外可以在docs/目录下或代码注释中添加更详细的设计文档、爬虫策略详解、清洗规则说明等这体现了严谨的工程习惯。7. 常见问题排查与实战技巧在实际操作中你几乎一定会遇到下面这些问题。这里记录了我的排查思路和解决方法。7.1 爬虫被屏蔽或返回错误数据现象请求返回403/404错误或返回的HTML内容不包含目标数据可能是验证页面。排查检查请求头确保User-Agent是有效的浏览器标识。有时还需要添加Referer或Accept-Language等头信息。用浏览器开发者工具仔细对比你的请求和浏览器正常请求的差异。检查频率抓取速度过快是最常见的原因。务必增加随机延时并考虑在抓取一定数量后暂停更长时间。检查Cookie/Session有些网站需要维持会话。可以使用requests.Session()对象来保持Cookie。查看Robots.txt访问http://目标网站/robots.txt确认你的爬取路径是否被明确禁止。尝试使用API再次用开发者工具仔细寻找隐藏的JSON API接口这通常是最稳定友好的数据获取方式。7.2 数据解析失败或字段为空现象BeautifulSoup找不到标签返回None。排查验证选择器将抓取到的HTML片段保存到本地文件用浏览器打开再次用开发者工具确认你使用的标签和属性路径是否正确。网站改版是常有的事。处理动态加载如果数据是JavaScript动态加载的requests获取的初始HTML里就没有。这时需要考虑使用Selenium或Playwright这类能模拟浏览器行为的工具。使用更灵活的查找方法除了class和id可以尝试用find结合字符串匹配如soup.find(li, textre.compile(湿度))。7.3 数据分析结果不符合常识现象计算出的平均温度高得离谱或者图表显示异常。排查回溯原始数据检查出问题的数据点在原始CSV文件中是什么样子。可能是爬虫解析时单位如“℃”没有去除干净导致数据被识别为字符串。检查数据类型用df.dtypes确认数值列确实是float或int而不是object。检查清洗逻辑回顾你的异常值处理代码是否错误地将合理数据剔除了或者填充缺失值时引入了系统性偏差可视化原始数据在清洗前先对原始数据做简单的分布图一眼就能看出那些“刺眼”的异常点。7.4 项目依赖包版本冲突现象在你的电脑上运行正常在别人的环境或服务器上报错。解决方案使用虚拟环境始终在venv或conda等虚拟环境中开发项目。精确记录依赖使用pip freeze requirements.txt生成依赖列表时最好手动维护一个核心依赖及其兼容版本的范围而不是记录所有包的精确版本。例如pandas1.4.0,2.0.0 requests2.28.0 beautifulsoup44.11.0 matplotlib3.5.0 seaborn0.11.0在README中明确说明Python版本和主要依赖。这个项目麻雀虽小五脏俱全。它强迫你面对数据科学中那些不那么“性感”但至关重要的部分数据的获取与治理。当你完整地走通一遍这个流程你会对“数据驱动”有更踏实、更深刻的理解。下次再看到任何数据分析或机器学习项目你都会本能地问出第一个问题你的数据是怎么来的本文还有配套的精品资源点击获取
网站建设高端定制企业官网