拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python爬虫可视化实战:从数据采集到图表展示的完整项目

Python爬虫可视化实战:从数据采集到图表展示的完整项目 我在带Python新手的过程中最常被问到的一句话就是“基础语法都过了一遍但真让我独立做点什么脑子还是一片空白。”如果你正好处在类似阶段大概率已经学了三四十天的Python看教程能看懂跟着敲也没问题但关掉视频自己动手就卡壳。我个人认为Day49正是突破这个瓶颈的关键节点。这一天最应该做的事情不是继续刷语法而是完整地走通一个真实项目用Python爬虫抓一份公开数据再用可视化把它变成一张能看懂、能分享的图表。这也是本次内容要解决的问题。我会把环境配置、爬虫思路、代码实现、可视化渲染、踩坑记录全部拆开讲一遍适合学完Python基础、想做一次综合实战的初学者参考也适合想从头梳理Python项目流程的朋友拿来当模板。1. day49阶段定位与项目思路设计1.1 入门课程走到第49天到底该学什么很多Python教程会把内容按天数切分前30天基本是变量、字符串、列表、字典、函数、文件读写、异常处理这些基础语法。第40天左右开始引入类、装饰器、生成器这些进阶概念。到第49天这个位置学员普遍已经具备几个能力能写100行以上的脚本能处理JSON和CSV文件能看懂简单的requests和pandas代码也知道matplotlib或者pyecharts的大致用法。但这个阶段最大的问题恰恰是“什么都知道一点但什么都没真正落地过”。初学者经常出现的一个现象是语法书翻完一遍会做课后习题但遇到“把某个网站的数据抓下来分析”这种需求完全不知道从哪一行开始写。所以我给day49定的主题很明确综合项目实战。目标不是学新语法而是把已经学过的零散知识点拼装成一个完整的工作流。从目标拆解、数据获取、数据清洗、可视化呈现到结果验收每个环节都要落到实处。这才是从“会语法”跨向“能做东西”最关键的一步。1.2 为什么选“公开数据爬取可视化”作为综合实战方向爬虫和可视化是Python应用里被提到最多的两个方向热搜词榜单上长期占据前排但初学者最容易在这两个方向上翻车。有人学到爬虫就急着去抓电商价格结果被反爬机制搞得怀疑人生有人学可视化只会画一堆花架子图表连数据源都是假的做出来的东西只能自嗨。Day49这个项目我刻意选了一条更稳的路径抓取公开气象数据清洗后做可视化分析。选择这个方向有四个好处数据源公开且合法。气象部门、环境监测站都有公开的数据接口不需要处理登录态和复杂反爬适合入门阶段聚焦在“数据处理流程”本身。数据形态丰富。既有数值型的温度、湿度也有分类型的天气现象能用来练习各种数据结构处理。可视化场景明确。温度趋势、降水量的空间分布、空气质量对比都能用折线图、柱状图、地图等图表展示效果直观。贴近日常。你会发现做出第一张“未来一周最高最低气温趋势图”之后学Python的动力完全不一样——因为代码真的解决了自己的问题。如果只是照搬教程里的示例数据画图你永远不会体会到“从零到一”的完整链路。真实的项目感觉必须从真实的数据链路里长出来。2. 项目完整拆解与核心代码实现2.1 项目结构与请求模块设计我设计这个项目时刻意保持了模块化结构没有把所有代码塞进一个文件。新手写项目最大的坑就是把所有逻辑写在一个300行的脚本里改一个功能全局报错。这个项目的目录结构如下weather_project/ ├── main.py # 项目入口串联整个流程 ├── data_fetcher.py # 数据获取模块 ├── data_cleaner.py # 数据清洗模块 ├── visualizer.py # 可视化模块 ├── requirements.txt # 依赖清单 └── output/ ├── raw_data.json # 抓取到的原始数据 ├── clean_data.csv # 清洗后的结构化数据 └── charts/ # 生成的图表文件这种划分的原因很简单每个模块只负责一件事出问题时能快速定位。data_fetcher挂了就去查网络请求visualizer出问题就跑排查可视化那一块不用整个项目从头到尾翻。data_fetcher.py的代码实现并不复杂但有几个细节直接影响成败。第一是请求头很多公开接口对请求头有基础的校验直接requests.get很容易被拒。我习惯在请求头里带上User-Agent和Accept字段伪装成真实浏览器访问import requests import json import time def fetch_weather_data(city_list, target_date): base_url https://xxx-api.example-data.com/weather headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Accept: application/json, text/plain, */* } result {} for city in city_list: params { city: city, date: target_date } try: response requests.get(base_url, headersheaders, paramsparams, timeout10) response.raise_for_status() data response.json() result[city] data.get(data, {}) time.sleep(0.5) # 控制请求频率避免高频访问 except requests.exceptions.RequestException as error: print(f[请求失败] {city}: {error}) return result if __name__ __main__: cities [北京, 上海, 广州, 成都, 西安] weather_data fetch_weather_data(cities, 2025-04-15) with open(output/raw_data.json, w, encodingutf-8) as file: json.dump(weather_data, file, ensure_asciiFalse, indent2)注意time.sleep(0.5)这一步看似简单实际上是对目标服务器的基本礼貌。即使请求的是公开接口高频密集访问也容易触发限流。我在实际项目中遇到过因为请求间隔太短IP被临时封禁的情况所以这个技巧对爬虫类项目普遍适用。2.2 数据清洗模块比抓数据更花时间的环节很多新手以为拿到JSON数据就万事大吉实际上原始数据的质量往往惨不忍睹。缺失字段、时间格式不统一、温度带单位、湿度写成了字符串都会在后续画图时形成一颗大雷。这是我在项目里专门划分data_cleaner模块的原因。以气温数据为例真实接口返回的字段可能长这样temperature: 23.5 ℃还可能是temp: 23.5不同数据源字段名和单位都不同。清晰之后才能进入分析环节。清洗的核心逻辑如下import pandas as pd import json import re def clean_weather_data(raw_fileoutput/raw_data.json): with open(raw_file, r, encodingutf-8) as file: raw_data json.load(file) rows [] for city, info in raw_data.items(): dates info.get(dates, []) temps info.get(temps, []) humidity info.get(humidity, []) for idx, date in enumerate(dates): temp_str temps[idx] if idx len(temps) else None humidity_str humidity[idx] if idx len(humidity) else None # 从字符串中提取数值 temp_value extract_number(temp_str) humidity_value extract_number(humidity_str) rows.append({ city: city, date: date, temperature: temp_value, humidity: humidity_value }) df pd.DataFrame(rows) df df.dropna(subset[temperature]) df[date] pd.to_datetime(df[date]) df df.sort_values([city, date]) df.to_csv(output/clean_data.csv, indexFalse, encodingutf-8-sig) return df def extract_number(text): if text is None: return None match re.search(r-?\d\.?\d*, str(text)) return float(match.group()) if match else None这里处理了三个常见问题字段缺失用None占位、字符串和数值混用通过正则提取、日期字符串统一为datetime类型。utf-8-sig编码是另一个容易被忽略的细节如果用utf-8直接写入CSV用Excel打开时中文会乱码加-sig后缀就没有这个问题。我在交付实际项目时被这个细节坑过不止一次。2.3 可视化模块pyecharts配置与图表组合可视化部分我放弃了matplotlib改用pyecharts。原因很简单pyecharts输出的图表是HTML格式交互性强鼠标悬停能看到详细数据一键缩放分享给朋友直接打开网页就行。对新手来说“做出来的东西能展示给别人看”比“概念上专业的静态图”更能维持学习热情。可视化模块的代码分成几个部分读取清洗后的CSV按城市分组绘制温度趋势折线图、降水量柱状图和城市对比图。以一个核心图表的配置为例from pyecharts import options as opts from pyecharts.charts import Line, Bar, Page def draw_temperature_trend(df): city_names df[city].unique() line Line(init_optsopts.InitOpts(width1200px, height600px)) for city in city_names: city_data df[df[city] city].sort_values(date) line.add_xaxis(city_data[date].dt.strftime(%m-%d).tolist()) line.add_yaxis( series_namecity, y_axiscity_data[temperature].tolist(), is_smoothTrue, symbol_size6, label_optsopts.LabelOpts(is_showFalse) ) line.set_global_opts( title_optsopts.TitleOpts(title多城市温度趋势对比), tooltip_optsopts.TooltipOpts(triggeraxis), legend_optsopts.LegendOpts(pos_leftcenter), yaxis_optsopts.AxisOpts(name温度(°C)) ) return line def draw_page(df): page Page(layoutPage.SimplePageLayout) page.add(draw_temperature_trend(df)) page.render(output/charts/weather_dashboard.html)画地图类图表时注意先确认对应的地图数据。pyecharts绘制中国城市地图需要echarts-china-cities-js这类扩展包否则地图只显示一个轮廓下面会提到这个具体报错如何处理。2.4 主流程拼接让脚本自己跑完全流程在main.py里把所有模块串起来这一步能直观展示一个自动化项目的完整生命周期from data_fetcher import fetch_weather_data from data_cleaner import clean_weather_data from visualizer import draw_page def main(): print(Step 1: 获取数据...) cities [北京, 上海, 广州, 成都, 西安] raw_data {} for city in cities: raw_data.update(fetch_single_city_data(city)) save_raw_data(raw_data) print(Step 2: 清洗数据...) df clean_weather_data() print(f清洗完成共 {len(df)} 条有效记录) print(Step 3: 生成可视化报告...) draw_page(df) print(全部完成图表已保存到 output/charts/weather_dashboard.html) if __name__ __main__: main()整个项目的操作体验是终端里输入python main.py等待几十秒钟直接打开HTML文件看到结果。在真实项目中这样的自动链路也可以把“抓取清洗展示”的全部环节纳入到定时任务里后续做成一个每天更新的小面板。3. 环境准备与部署实操心得3.1 VSCode还是PyCharm不用再纠结的选型建议热搜词里关于编辑器配置的搜索量常年居高不下说明很多新手在第一步就被卡住了。我自己的建议是入门阶段用VSCode做数据分析和爬虫完全够用启动快、插件生态好PyCharm更适合大型工程但新手面对它那一堆配置项容易陷入选择困难。VSCode配置Python环境只需要三步。第一步安装Python插件这一步可以用扩展商店完成。第二步按CtrlShiftP打开命令面板输入“Python: Select Interpreter”选择虚拟环境或者系统解释器。第三步打开终端验证是否能直接进入python交互模式。我特别强调一个很多人忽略的细节VSCode里终端默认用的可能是PowerShell需要保证终端里激活了你正在用的那个Python解释器。最常见的报错“module not found: requests”多半就是因为终端里运行的Python和VSCode右下角选择的解释器不是同一个。3.2 依赖安装的正确位置虚拟环境和requirements.txt依赖管理也是初学者最不重视、但实际项目里最影响体验的环节。项目开始时第一件事应该是在项目根目录执行python -m venv venv然后激活虚拟环境。Windows和macOS/Linux激活命令不一样这个细节值得单独强调# Windows PowerShell venv\Scripts\activate # macOS/Linux source venv/bin/activate激活之后再安装requests、pandas、pyecharts全部装进虚拟环境里不会污染全局Python。我给这个项目准备的requirements.txt如下requests2.31.0 pandas2.0.0 pyecharts2.0.0 openpyxl3.1.0把依赖写进requirements.txt换电脑、换环境、让别人复现项目时一行命令就能搞定环境pip install -r requirements.txt这个习惯早期养成后面做任何项目都会受益。对初学者来说最理想的安装方式是在虚拟环境中慢慢体会包管理逻辑而不是一股脑把常用库全部装上。3.3 镜像源选择与安装速度优化国内pip下载最痛苦的经历就是大包因为网络波动反复失败。这里分享一个提高安装成功率的做法安装时指定国内镜像源测试下来清华源和阿里源都比较稳定。pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple也可以把镜像写到全局配置文件中这样以后安装任何包都不用手动指定。建议配置项如下[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple trusted-host pypi.tuna.tsinghua.edu.cn到这里环境问题基本就解决了。我在多个新人电脑上实测按这种方式配置后安装依赖环节的报错率下降了90%以上。4. 常见问题与排查技巧实录4.1 请求阶段报错SSL证书和连接超时“NameError: name ‘xxx’ is not defined”和“requests.exceptions.SSLError”这两个问题出现的频率最高。前者基本上是代码少写了导入语句def函数外没有import requests后者是SSL证书校验失败。SSL报错的快速排查步骤先确认目标接口是否支持HTTP如果确定是HTTPS可以在请求参数里加上verifyFalse试试但仅限本地测试。真实项目中遇到证书问题更规范的思路是更新根证书或者检查系统时间是否正确——证书校验失败很多时候是因为电脑系统时区不对。连接超时则要优先检查你的网络环境是否正常其次是接口地址是否写错。为requests增加timeout参数是规范做法但初学者经常忘记一旦目标服务器响应慢程序会一直挂起看起来就像死机了一样。4.2 数据清洗阶段中文乱码和类型转换错误清洗阶段被问得最多的问题是Excel打开CSV中文乱码解决方式上面已经提到写入时用encodingutf-8-sig即可。类型转换错误大多是“could not convert string to float”常见于字段仍然包含“%”或“℃”这样的符号正则提取时要格外注意。我自己的经验是清洗逻辑不要写得太复杂原则就一条——每个字段都先用type()看清原始类型再决定怎么处理。多数清洗问题都能靠这个检查动作提前规避。4.3 可视化阶段图表不显示数据或地图空白pyecharts在Jupyter Notebook里不显示是常见问题排查方向通常有两个一是确认输出为HTML时是否设置了正确的渲染路径二是检查是否调用了.render_notebook()方法。如果直接在普通Python脚本里运行render_notebook根本不会生效必须用.render()生成HTML文件后用浏览器打开。地图空白的问题像上面提到的原因是缺少扩展地图包。pyecharts从某个版本开始把地图数据拆出来了比如画中国地图需要安装对应echarts-china-js扩展。解决方案很简单pip install echarts-china-provinces-pypkg echarts-china-cities-pypkg另外在图表显示中文时默认字体在某些Linux环境下会变成方框需要显式设置字体配置或者检查系统是否安装了中文字体。4.4 词条八卦Python爱心代码和爬虫可视化界面热点词里还有两个关注度很高的方向这里顺便提一嘴。一个是“Python爱心代码”这个我非常建议在day49之后当娱乐练习做——本质上就是用turtle或matplotlib画一个心形曲线它不涉及复杂算法却能把坐标变换、循环、函数调用这几个基础概念串起来。我自己就用它作为新人学习曲线理解的一个补充练习。另一个是“Python爬虫可视化界面”这个可以作为day49项目的进阶方向把已经做好的爬虫和可视化逻辑用Flask或Streamlit包一层简单的Web界面在浏览器里通过下拉框选择城市、选择日期范围点击按钮后动态更新图表。这个进阶我今天不在篇幅里展开但思路值得记住核心的数据抓取和可视化逻辑你已经有了剩下的只是给它穿上一件“交互界面”的外衣。5. 让day49项目持续生长的三个方向5.1 给项目加上定时任务变成自动更新面板项目做完后我建议做一次升级在本地设置定时任务每天自动执行一次main.py。Windows下可以使用任务计划程序macOS/Linux下可以配置crontab任务。这样你每天打开浏览器看到的都是最新数据真实感会瞬间提升很多。配置示例每天早上8点运行# macOS/Linux crontab 0 8 * * * cd /path/to/weather_project /path/to/venv/bin/python main.py logs/cron.log 215.2 扩展数据源把多个接口的数据合并分析升级方向可以是将“多个数据源的同类数据进行一致性校验”这是一个非常实战的训练不同接口对温度的处理方式、时区标准都不同把它们对齐本身就是一次深度的数据工程练习。这里不写具体代码强调的是项目成长路径的价值。5.3 用Python小技巧增加收藏价值最后再分享我个人的一个偏好在项目完成后我会把生成的图表文件夹分享给朋友顺便在终端里跑一小段生成“爱心代码”的脚本作为学习的一个趣味注脚。这个习惯没有实际业务价值但对维持长期学习的兴趣真的有用。毕竟不能被兴趣支撑的项目很难走得远。Day49只是一个数字但它代表了一个关键的转换点从跟着教程复制代码到看着自己的项目需求动手写代码。这个项目的核心收获不是那几张图表而是你已经走过了一条完整的“数据获取清洗呈现”链路。后面的路照这个模式继续加功能就好。
返回列表