Python实战:爬取微博,获取南京地铁每日客流数据

在这篇文章中,我们将使用 Python 进行网络爬虫,爬取微博上的南京地铁每日客流数据。

一、分析网页

在“南京地铁”微博主页搜索“昨日客流”关键词,搜索到每天发布的昨日客流数据。

“南京地铁”微博主页地址https://weibo.com/u/2638276292

在浏览器开发者工具界面查看相关请求 url、payload、response 等参数,可以很清晰的分析出爬虫逻辑。

爬虫代码就不展开说了,下面直接给出完整代码。分析过程可以参考之前公众号文章,写过好几篇类似的文章。

二、爬取数据

编写 python 代码,获取到过去 1035 天含有“昨日客流”关键词的微博,并保存为一个 excel 表。

保存的 excel 表如下,created_at字段是微博发送时间,text_raw字段是微博正文。

三、解析数据

对created_at字段进行正则表达式,提取出微博发送时间、前一天日期。

from datetime import datetime, timedelta# 提取出日期字符串
text = "Mon Jan 15 09:03:10 +0800 2024"
date_split = text.split()
date_str = date_split[5] + " " + date_split[1] + " " + date_split[2] + " " + date_split[3]# 将字符串转换为日期格式
created_date = datetime.strptime(date_str, '%Y %b %d %H:%M:%S')
print(created_date)# 计算客流日期,只保留年月日
traffic_date = (created_date - timedelta(days=1)).date()
print(traffic_date)

对text_raw字段进行正则表达式,提取出每天每条地铁线路的客流数量。

import retext = "#昨日客流# 南京地铁12月31日客运量408.6,其中1号线117.7,2号线102.8,3号线93.6,4号线17.9,7号线13.6,10号线15.2,S1号线13,S3号线8.7,S6号线6.5,S7号线1.9,S8号线13.7,S9号线3.9(以上单位:万)"
# 提取日期
date_pattern = r'\d{1,2}月\d{1,2}日'
date = re.search(date_pattern, text).group()# 提取客运量
traffic_all = re.findall(r"客运量(\d+\.{0,1}\d?)", text)[0]
print(traffic_all)# 提取每条地铁线路的客运量
pattern = r"(S?\d+号线\d+\.{0,1}\d?)"
matches = re.findall(pattern, text)
print(matches)data = {}
for match in matches:line_number = re.findall(r"(S?\d+号线)", match)[0]traffic_volume = re.findall(r"号线(\d+\.{0,1}\d?)", match)[0]data["str_date"] = datedata[line_number] = traffic_volume
print(data)

image-20240131195148751

四、查看异常数据

使用布尔索引筛选出包含空值的行

# 使用布尔索引筛选出包含空值的行
print(traffic_df[traffic_df.isnull().any(axis=1)])

Pycharm 显示 12 月 21 日、6 月 4 日、6 月 5 日、4 月 27 日的行存在空值:

12 月 21 日空值如下:

6 月 4 日、6 月 5 日空值如下:


4 月 27 日空值如下:

对比原始 excel,可以发现产生空值的原因是人工发微博有细节错误,导致正则表达式没有匹配出数据。

例如“10 号线,14.5”、“4 线 14.9”、“4 线 10.2”、“1 号线,86.3”,这几个字符串由于人工输入错误,没有被正则表达式匹配出来。

五、完整代码

1、爬取数据部分的完整代码:

import requests
import pandas as pdcontent_list = []for page in range(1, 200):headers = {"Cookie": "","User-Agent": ""}data = {"page": page,"uid": "2638276292","q": "昨日客流",}url = f"https://weibo.com/ajax/statuses/searchProfile?"content_json = requests.get(url=url, headers=headers, params=data).json()print("第", page, "页,本页", len(content_json['data']['list']), "条数据", content_json['data']['list'])# df = pd.DataFrame(content_json['data'])if len(content_json['data']['list']) > 0:df = pd.json_normalize(content_json['data']['list'], errors='ignore')df = df.loc[:, ['created_at', 'text_raw']]content_list.append(df)else:break# concat合并Pandas数据
df = pd.concat(content_list)
df.to_excel(f"南京地铁客运量-昨日客流1.xlsx", index=False)
print("保存完成!")# 查看 DataFrame 的行数和列数。
rows = df.shape
print("请求得到的表格行数与列数:", rows)

2、处理数据部分的完整代码:

import re
import pandas as pd
from tqdm import tqdm
from datetime import datetime, timedeltapd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 100)
pd.set_option('display.width', 1000)def extract_info(created_at, text_raw):# 从created_at字段,提取出日期text1 = created_atdate_split = text1.split()date_str = date_split[5] + " " + date_split[1] + " " + date_split[2] + " " + date_split[3]# 将字符串转换为日期格式created_date = datetime.strptime(date_str, '%Y %b %d %H:%M:%S')# 计算客流日期,只保留年月日traffic_date = (created_date - timedelta(days=1)).date()# 从text_raw字段,提取日期、客运量text2 = text_rawdate_pattern = r'\d{1,2}月\d{1,2}日'date = re.search(date_pattern, text2).group()# 提取客运量traffic_all = re.findall(r"客运量(\d+\.{0,1}\d?)", text2)[0]# 提取每条地铁线路的客运量pattern = r"(S?\d+号线\d+\.{0,1}\d?)"matches = re.findall(pattern, text2)# data字典用来存放提取出来的数据data = {}for match in matches:line_number = re.findall(r"(S?\d+号线)", match)[0]traffic_volume = re.findall(r"号线(\d+\.{0,1}\d?)", match)[0]data["created_date"] = created_datedata["traffic_date"] = traffic_datedata["str_date"] = datedata["traffic_all"] = float(traffic_all)data[line_number] = float(traffic_volume)# 提取出来的数据存到traffic_list列表traffic_list.append(data)if __name__ == '__main__':# traffic_list列表存放数据traffic_list = []df = pd.read_excel("./南京地铁客运量-昨日客流.xlsx")# drop_duplicates()函数删除重复行df = df.drop_duplicates()tqdm.pandas(desc='提取文本信息进度条', unit="请求")  # tqdm显示进度条df.progress_apply(lambda x: extract_info(x['created_at'], x['text_raw']), axis=1)traffic_df = pd.DataFrame(traffic_list)# 使用布尔索引筛选出包含空值的行print("包含空值的行如下:")print(traffic_df[traffic_df.isnull().any(axis=1)])# 保存为excel表格traffic_df.to_excel(f"南京地铁2023年客运量数据.xlsx", index=False)print("保存完成!")# 查看 DataFrame 的行数和列数。rows = traffic_df.shapeprint("得到的表格行数与列数:", rows)

六、数据可视化

最后,我们还可以使用数据可视化工具(如 Matplotlib、Seaborn、Pyecharts 等)将南京地铁每日客流数据可视化,以便更直观地分析数据。

例如:将每月的客运量进行统计,绘制一个按月份的折线图。

代码如下:

import pandas as pd
import matplotlib.pyplot as plt# 读取Excel文件
df = pd.read_excel('南京地铁2023年客运量数据.xlsx')# # 将traffic_date列转换为日期类型
# df['traffic_date'] = pd.to_datetime(df['traffic_date'])# 计算每月的客运量总量
monthly_traffic = df.groupby(pd.Grouper(key='traffic_date', freq='M'))['traffic_all'].sum().reset_index()# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 绘制折线图
plt.figure(figsize=(12, 6))
plt.plot(monthly_traffic['traffic_date'].dt.strftime('%Y-%m'), monthly_traffic['traffic_all'])
plt.xlabel('月份')
plt.ylabel('月客运量')
plt.title('每月客运量总计')
plt.xticks(rotation=45)
plt.grid()# 在图上标记每个月的客运量数字
for i, row in monthly_traffic.iterrows():plt.annotate(f"{row['traffic_all']:.0f}",(row['traffic_date'].strftime('%Y-%m'), row['traffic_all']),xytext=(10, 10),textcoords='offset points',ha='left',va='bottom',fontsize=12)plt.show()

生成的折线图如下:

可以看到 2023 年 1 月份和 2 月份客运量明显偏低,当时疫情对出行还是产生较大影响。受后续相关政策调整后,客运量数据从 2 月份开始才逐渐恢复正常水平。

由于数据可视化不是本篇文章重点,就不展开写了,可以移步参考之前写过的几篇数据可视化的文章。

七、总结

在这篇文章中,我们使用 Python 进行网络爬虫,爬取了微博上的南京地铁每日客流数据,并且进行了数据处理和数据可视化。

爬取数据环节较为简单,多看几篇我之前发的文章,都可以轻松写出来爬虫部分的代码。

由于微博是由地铁公司的工作人员每天人工编辑发送的,其中不免有数据格式不完全一致,这给数据处理环节增加了复杂度。

本文首发在“程序员coding”公众号,欢迎关注与我一起交流学习。

本文数据集已经上传到公众号,后台回复“南京地铁”可以自取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于视觉的移载协作机器人机床上下料末端纠偏算法

摘 要 针对复合机器人在机床上下料中的定位方法,本文主要关注识别机床卡盘和末端作业面的定位。首先分 析了复合机器人在机床上下料过程中的工作原理及其基本结构,包括 AGV (自动导引车)和协作机器人 的功能及特点。然后,详细阐述了如何使用视觉系统和纠偏算法来…

京东采销急眼,隔空喊话“针对”拼多多,焦虑之下为哪般?

农历新年将至,无论是线下各大商超还是线上电商平台,皆为年终大促而“忙的不亦乐乎”,尤其是近期发生的京东采销人员在直播间向拼多多喊话,“恳请拼多多停止屏蔽,恳请拼多多直接比价”,更是将年底这场朴实无…

flink cdc,standalone模式下,任务运行一段时间taskmanager挂掉

在使用flink cdc,配置任务运行,过了几天后,任务无故取消,超时,导致taskmanager挂掉,相关异常如下: 异常1: did not react to cancelling signal interrupting; it is stuck for 30 s…

ElasticSearch基础用法

什么是ElasticSearch? Elasticsearch是一个开源的、分布式的、实时的搜索和分析引擎。它允许用户近乎实时地存储、检索大量数据,并能够高效地对其进行全文搜索、聚合和分析。 部署ES和Kibana 通常采用docker-compose部署ES(ElasticSearch)服…

react-jss书写样式 与 react-intl 国际化的使用 与 classnames 动态css的使用

目录 react-jss的使用react-intl 国际化的使用App.tsxIntlProvider 配置ConfigProvider组件/router/indexlocaleslocales / zh.json || en.json 组件中使用 国际化 classnames 动态css的使用 react-jss的使用 实现组件化样式、动态样式、避免样式冲突 npm install react-jss …

React 组件中怎么做事件代理

在 React 组件中使用事件代理可以使用以下方法&#xff1a; 使用 on 方法来绑定事件监听器&#xff1a; class MyComponent extends React.Component {handleClick(event) {if (event.target.tagName BUTTON) {console.log(Button clicked);}}render() {return (<div onC…

如何写好论文——(3)研究选题的三种途径

一、填补研究空白——创新 在前人的研究基础上发现问题、提出创新&#xff0c;在技术上具有挑战性 关键&#xff1a;提出我们在课题上创新的部分&#xff0c;它可能是新的解决方案&#xff0c;从其他领域借鉴过来的新的想法 因为它是老问题&#xff0c;所以需要研究前人已经…

速盾:服务器高防CDN能防御哪些网络攻击

摘要&#xff1a;本文将探讨服务器高防CDN的技术&#xff0c;以及它可以有效防御哪些网络攻击。我们将介绍DDoS攻击、CC攻击、恶意爬虫等常见网络攻击&#xff0c;并说明服务器高防CDN通过其强大的防御技术如高防IP、智能分流等如何应对这些攻击。此外&#xff0c;我们还将回答…

寒假思维训练day17 C. Equal Frequencies

不知不觉已经过了差不多一个月了&#xff0c;坚持一件事情还是有点收获的&#xff0c;今天更新一道1600的构造。 寒假训练计划day17 摘要&#xff1a; Part1 题意 Part2 题解 (有数学推导&#xff0c;latex形式) Part3 代码 (C版本&#xff0c;有详细注释) Part4 我对构造题…

基于YOLOv7算法的高精度实时安全帽和背心目标检测系统(PyTorch+Pyside6+YOLOv7)

摘要&#xff1a;基于YOLOv7算法的高精度实时安全帽和背心目标检测系统可用于日常生活中检测与定位安全帽和安全背心&#xff0c;此系统可完成对输入图片、视频、文件夹以及摄像头方式的目标检测与识别&#xff0c;同时本系统还支持检测结果可视化与导出。本系统采用YOLOv7目标…

SpringBoot2整合了Rabbitmq以后,有些情景不需要初始化和连接Rabbitmq,所以需要怎么处理呢?

问题提出&#xff0c;最近有个需求&#xff0c;有的场合项目需要连接Rabbitmq&#xff0c;有些场合项目就不需要连接&#xff0c;再不需要连接的时候&#xff0c;还必须的安装Rabbimq服务&#xff0c;徒增时间消耗&#xff0c;所以需要处理一下。 在yml中配置如下&#xff1a; …

【电子科技大学】计算机高级图形学总复习

第一章&#xff1a;绪论 图形学和图像学 走样的原因和反走样 走样指的是&#xff1a;用离散量表示连续量引起的失真 反走样&#xff1a;为了提高图形的显示质量&#xff0c;需要减少或消除因走样带来的阶梯形或闪烁的效果&#xff0c;用于减少或消除这种效果的方法称为反走样…

【51单片机Keil+Proteus8.9】门锁控制电路

门锁控制电路 二、设计思路 电路设计 1.电源部分&#xff1a;使用BATTERY为整个电路提供电源&#xff0c;可以在电路中加入一个电 源开关&#xff0c;以便控制电源的开启和关闭。 2.处理器部分&#xff1a;使用AT89C51芯片作为主处理器&#xff0c;通过编写程序实现门锁的 …

头歌C++之do-while循环性质

目录 第1关:求1到n间所有整数的和 本关必读 本关任务 测试说明 第2关:用牛顿迭代法求方程的实根 本关必读 本关任务 测试说明

代码随想录算法训练营第17天(二叉树5)| 找树左下角的值二叉树的路径总和从中序与后序遍历序列构造二叉树从前序与中序遍历序列构造二叉树

513.找树左下角的值 leetcode题目地址 题目链接/文章讲解/视频讲解 如果使用递归法&#xff0c;如何判断是最后一行&#xff1a; 其实就是深度最大的叶子节点一定是最后一行。 //迭代法 class Solution { public:int findBottomLeftValue(TreeNode* root) {queue<TreeNod…

《Lua程序设计》-- 学习9

迭代器和泛型for 迭代器和闭包 迭代器&#xff08;iterator&#xff09;是一种可以让我们遍历一个集合中所有元素的代码结构。在Lua语言中&#xff0c;通常使用函数表示迭代器&#xff1a;每一次调用函数时&#xff0c;函数会返回集合中的“下一个”元素。 一个闭包就是一个…

SD-WAN有哪些组网方式?

随着企业网络需求的不断增长和变化&#xff0c;SD-WAN作为一种先进的网络架构技术&#xff0c;提供了多种灵活的组网方式&#xff0c;以适应不同企业的需求。本文将介绍SD-WAN常见的几种组网方式&#xff0c;帮助企业更好地理解如何利用SD-WAN构建高效的网络。 1、点对点&#…

离线使用Element UI和Vue

需要依赖如下&#xff1a; 1.vue.js; 2.index.js(Element UI) 3.index.css(Element UI) 4.element-icons.ttf(Element UI字体) 5.element-icons.woff(Element UI图标) 下载链接如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1nGOi0Vm_xExRGmVp6oVLoA 提取…

【Android】屏幕锁

屏幕锁&#xff0c;就是锁住屏幕不让用户误触摸&#xff0c;从开发者的角度看就是不响应用户的点击事件。 屏幕锁界面 可以自己创建一个布局文件&#xff0c;或者直接创建一个View&#xff08;例如ImageView&#xff09;。 参数LayoutParams mLayoutParams new LayoutParam…

【笔记】React-Native跟Android交互--简单示例

/** * 使用命令 npx react-nativelatest init DemoRN创建项目 * * "react": "18.2.0", * "react-native": "0.73.2" * * 官网有详细教程&#xff1a;https://reactnative.dev/docs/native-modules-android */ 一、RN invoke androi…