前言
今天,我来说说怎么抓取宿舍电费的过程。我们学校是在完美校园交电费的,我们可以不用取抓包完美校园的数据接口,我们可以直接登录学校的一卡通网站,每个学校都有,大家可以自己找找,这里我为什么要抓包呢,因为学校提供的网站已经打不开了,这里就不介绍怎么抓包了。
以下是几个常用的抓包工具:
Wireshark:这是一款开源的网络分析工具,支持多种操作系统。它可以捕获和分析网络数据包,并提供详细的统计和报告。
Fiddler:这是一款基于 Windows 的 HTTP 调试代理工具,可以帮助你捕获和分析 HTTP 流量。它还提供了一些高级功能,例如自定义规则和脚本。
Charles:这是一款跨平台的抓包代理工具,可以用于捕获 HTTP 和 HTTPS 流量。它也提供了一些高级功能,例如修改请求和响应,并支持网络模拟。
Burp Suite:这是一款专业的 Web 应用程序安全测试工具,可以用于捕获和分析 HTTP 和 HTTPS 流量。它还提供了许多高级功能,例如漏洞扫描和自定义脚本。
接下来,我们开始登录,一般账号是自己的学号,密码是身份证后六位,我们登录之后,就可以看到电费充值的入口,我们点击之后,会看到这样的页面。
接下来,就是数据接口的分析了,我们多次调试,我们可以看到这样的结果,每个学校都是一样的,用几个参数来确定宿舍的电费查询接口。
获取楼号id
我们学校每个宿舍楼对应一个id,我们要是数据是怎么定义的,并不是一号楼对应的id就是1。这个接口需要我们传cookies,我这里就不放上面了,每个学校的情况可能不一样,大家可以自己调整代码,不过,我们学校的参数并没有加密,倒是简单了不少。
import requests
headers = {
"X-CSRF-TOKEN": "6d51ac80-b777-4a26-99a1-06bfbf65360f",
}
cookies = {
"JSESSIONID": "XXXX"
}
url = "http://218.22.140.88:8181/epay/electric/queryelectricarea"
data = {
"sysid": "1"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
print(response)
buils = response.json()['buils']
for buil in buils:
buiId = buil['buiId']
buiName = buil['buiName']
print(buiId,buiName)
我们这里定义了headers和cookies两个字典。headers字典包含了一个键为"X-CSRF-TOKEN"的项,对应的值是"6d51ac80-b777-4a26-99a1-06bfbf65360f"。这个值可能是与服务器进行身份验证或防止跨站请求伪造(CSRF)的令牌。cookies字典包含了一个键为"JSESSIONID"的项,对应的值是"XXXX"。这个值可能是用于保持用户会话状态的令牌。,也就是我们登录信息。
我们这里要注意,cookies有时效,还有那个X-CSRF-TOKEN也是有时效的,短期的使用是没有问题的。
我们使用response.json()方法将响应的内容转换为JSON格式,并将其存储在buils变量中。然后使用for循环遍历buils中的每个元素,并分别提取出每个元素的"buiId"和"buiName"的值,看看效果如何。
1 15号楼A
8 10号楼A
9 10号楼B
10 11号楼A
11 11号楼B
12 12号楼A
13 12号楼B
14 13号楼A
15 13号楼B
16 14号楼A
17 14号楼B
78 15号楼B
85 1号楼A
86 1号楼B
87 2号楼A
88 2号楼B
89 3号楼A
90 3号楼B
91 4号楼A
92 4号楼B
93 5号楼A
94 5号楼B
95 6号楼A
96 6号楼B
97 7号楼A
98 7号楼B
99 8号楼A
100 8号楼B
101 9号楼A
102 9号楼B
199 27号楼
200 29号楼
201 30号楼
202 31号楼
203 32号楼
233 16号楼A
234 16号楼B
247 33号楼
获取房间号
我们拿到了宿舍楼的id之后,我们接下来,就是拿到每个房间的id,只有通过这个,我们才能准确的查询到电费。
import requests
headers = {
"X-CSRF-TOKEN": "bee9698b-79a1-4c38-b5e0-2b0937fc3a28",
}
cookies = {
"JSESSIONID": "XXX"
}
url = "http://218.22.140.88:8181/epay/electric/queryelectricrooms"
data = {
"sysid": "1",
"area": "1",
"district": "1",
"build": "1", # 楼号
"floor": "1"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
print(response)
rooms = response.json()['rooms']
for room in rooms:
roomId = room['roomId']
roomName = room['roomName']
print(roomId, roomName)
我们这里和上面代码差不多,只不过,请求的地址变了,还有额外加了几个参数。"http://218.22.140.88:8181/epay/electric/queryelectricrooms"这个URL是查询房间号的API接口,用于查询房间号的相关信息。我们发送的数据("sysid"、"area"、"district"、"build"、"floor")是用来过滤或查询这些信息的参数。
我们来执行这段程序,让其输出每个房间的房间ID和房间名字,这里就展示截图了:
获取单个房间的电费
我们到这里就可以实现我们需要查询电费的功能了,我们完全可以抓这个数据,为什么我前面还是说了那么多,我主要还是为后面的内容做铺垫。
import requests
headers = {
"X-CSRF-TOKEN": "6d51ac80-b777-4a26-99a1-06bfbf65360f",
}
cookies = {
"JSESSIONID": "XXX"
}
url = "http://218.22.140.88:8181/epay/electric/queryelectricbill"
data = {
"sysid": "1",
"roomNo": "1602",
"elcarea": "1",
"elcbuis": "9"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
# print(response)
restElecDegree = response.json()['restElecDegree']
print(restElecDegree)
("sysid"、"roomNo"、"elcarea"、"elcbuis")参数就可以查询每个房间的电费,执行的结果如下:
{'retcode': 0, 'retmsg': '成功', 'multiflag': False, 'restElecDegree': 13.0}
获取整个学校电费
我们发现查询电费的数据接口就是这个样子的:
url = "http://218.22.140.88:8181/epay/electric/queryelectricbill"
data = {
"sysid": "1",
"roomNo": roomId,
"elcarea": "1",
"elcbuis": buiId,
}
我们只要获取到roomId和buiId,就可以,也就是我们前面讲的获取楼号和房间号。拿到这些数据,我们就可以抓取整个学校的电费了,我们每隔一段时间采集一次,我们就可以分析学校用电情况。
import time
import requests
import csv
f = open('全校电费.csv', mode='w', encoding='utf-8_sig', newline='')
csv_writer = csv.DictWriter(f, fieldnames=['楼号', '楼号ID', '房间名称', '房间号', '电费'])
csv_writer.writeheader()
headers = {
"X-CSRF-TOKEN": "bee9698b-79a1-4c38-b5e0-2b0937fc3a28",
}
cookies = {
"JSESSIONID": "XXX"
}
def get_buiId():
url = "http://218.22.140.88:8181/epay/electric/queryelectricarea"
data = {
"sysid": "1"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
buils = response.json()['buils']
for buil in buils:
buiId = buil['buiId'] # 楼号ID
buiName = buil['buiName'] # 楼号
# print(buiId,buiName)
get_roomId(buiId, buiName)
def get_roomId(buiId, buiName):
print("正在查询",buiName,"编号为",buiId)
url = "http://218.22.140.88:8181/epay/electric/queryelectricrooms"
data = {
"sysid": "1",
"area": "1",
"district": "1",
"build": buiId, # 楼号
"floor": "1"
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
# print(response)
rooms = response.json()['rooms']
for room in rooms:
roomId = room['roomId']
roomName = room['roomName']
# print(roomId, roomName)
get_restElecDegree(buiId, buiName, roomId, roomName)
# time.sleep(0.5)
def get_restElecDegree(buiId, buiName, roomId, roomName):
print("正在查询", roomName, "编号为", roomId,"电费")
url = "http://218.22.140.88:8181/epay/electric/queryelectricbill"
data = {
"sysid": "1",
"roomNo": roomId,
"elcarea": "1",
"elcbuis": buiId,
}
response = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
restElecDegree = response.json()['restElecDegree']
# print(buiId, buiName, roomId, roomName, restElecDegree)
dit = {
'楼号': buiName,
'楼号ID': buiId,
'房间名称': roomName,
'房间号': roomId,
'电费': restElecDegree,
}
csv_writer.writerow(dit)
get_buiId()
我们运行看下效果。
数据分析
我们这里就获取到了一次数据,就不做数据分析了,不过要使用Python进行电费数据分析,可以按照以下步骤:
- 导入所需的库和数据
首先需要导入数据分析所需的Python库,如pandas、numpy和matplotlib等。然后将电费数据导入到一个pandas的数据框中(DataFrame)。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.read_csv('全校电费.csv')
- 数据清洗
接下来需要对数据进行清洗,包括去除重复值、缺失值和异常值等。例如,可以使用pandas的drop_duplicates()方法去除重复值:
df.drop_duplicates(inplace=True)
可以使用pandas的isnull()方法查找缺失值,并使用dropna()方法删除包含缺失值的行:
df.isnull().sum() # 查找缺失值
df.dropna(inplace=True) # 删除包含缺失值的行
可以使用箱线图或者散点图等方法查找并删除异常值:
plt.boxplot(df['电费'])
df = df[df['电费'] < df['电费'].quantile(0.99)]
- 数据分析
接下来可以对数据进行分析,并使用可视化方法展示分析结果。例如,可以计算月度电费的平均值、中位数和标准差:
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
monthly_df = df.resample('M').mean()
monthly_df['电费'].describe() # 计算统计量
然后可以使用matplotlib绘制折线图或柱状图展示,并加上适当的标签和标题等:
plt.plot(monthly_df.index, monthly_df['电费'])
plt.xlabel('时间')
plt.ylabel('月度平均电费')
plt.title('电费趋势图')
- 数据可视化
数据可视化可以更好地展示数据分析结果,可以使用matplotlib、seaborn和plotly等库绘制各种图表,如折线图、柱状图、散点图、热力图等,以便更好地理解数据。
import seaborn as sns
sns.scatterplot(x='用电量', y='电费', data=df)
以上是使用Python对电费数据进行数据分析的基本步骤,具体分析方法可以根据数据特点和需要进行调整和改进。
总结
我们本文详细介绍了如何采集单个房间电费,并延展到获取全校电费并且做可视化分析。