1. motivation
随着气温回升,南方已进入到需要靠着冷空调度日的季节了。最近宿舍电费“蹭蹭蹭”地往上涨,宿舍舍友轮番充值了许多次。为了搞清楚自己宿舍每日用电的情况,笔者从我校充值小程序上爬取了本人宿舍自开学来的用电情况。出于隐私保护的目的,本文仅展示爬取思路和核心代码,cookie、header、url等核心信息,恕不展示。
2. 如何从小程序上爬取数据?
小程序不同于网页。网页在地址栏有显性的网址和明确的请求方式(get或post),而小程序的网址和请求方式相对隐性,但并不意味着没有!这时,我们就需要借助抓包软件进行辅助操作。笔者偏好于使用 fiddler+SwitchyOmega 的组合,对小程序进行抓包。
由于本文初衷是展示思路,不过多讲解技术上的操作。感兴趣的读者,可自行查阅相关操作方法。日后如有时间,笔者会专门写一篇文章,讲解 fiddler和SwitchyOmega的下载与配置,以及它们的使用技巧。
参考资料:
安装 SwitchyOmega 最简单的方法_proxy switchyomeg安装包-CSDN博客
https://www.cnblogs.com/cfzy/p/16595998.html
3. 核心代码展示
第一,导入相关的package。
import requests
import json
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
第二,定义函数,用来爬取宿舍的基本信息。
def crawl_get_base_info(floor,room):
'''
target
----
obtain information of a room.
parameter
----
floor (str): the number of floor
room (str): the number of room
return
----
a dict
'''
import warnings
warnings.filterwarnings("ignore")
url = "XXXXXXXXXXXXXXXXXXXX" # 网址脱敏
payload = "XXXXXXXX{floor}XXXX{room}" # payload脱敏
headers = {
'Host': 'XXX',
'Connection': 'XXX',
'Content-Length': 'XXX',
'sec-ch-ua': 'XXX',
'sec-ch-ua-mobile': 'XXX',
'Authorization': 'X',
'User-Agent': 'XXX',
'Content-Type': 'XX',
'Accept': 'XX',
'synjones-auth': 'XXX',
'sec-ch-ua-platform': 'XXX',
'Origin': 'XXX',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'XXXX',
'Accept-Encoding': 'XXXX',
'Accept-Language': 'zh-CN,zh;q=0.9'
} # 脱敏
response = requests.request("POST",
url,
headers=headers,
data=payload.format(floor=floor,room=room))
return json.loads(response.text)['map']['data']
第三,定义函数,用来获取我们宿舍的电量电费。
def crawl_electric_vol_fare(datelist,floor,room):
'''
target
----
crawl electric volume and fare
parameter
----
datelist (list): the time period list
floor (str): the number of floor
room (str): the number of room
return
----
a dataframe
'''
import warnings
warnings.filterwarnings("ignore")
url = "XXXX&date={date}&comAddress={comAddress}&XXXX&room={room}"
payload = {} # get方式无此参数
headers = {'Host': 'XX',
'Connection': 'X',
'sec-ch-ua': 'XX',
'Accept': 'XX',
'synjones-auth': 'bearerXXX',
'sec-ch-ua-mobile': 'XX',
'Authorization': 'XX',
'User-Agent': 'XXX',
'sec-ch-ua-platform': 'XX',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'XXX',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9'
} # 脱敏
base_info = crawl_get_base_info(floor=floor,room=room) #调用第二步定义的函数
piplineName = base_info['piplineName']
comAddress = base_info['comAddress']
buildingID = base_info['buildingID']
df = pd.DataFrame(columns=['日期', '日结算用量', '日结算金额'])
for i in datelist:
response = requests.request("GET",
url.format(date=i,
comAddress=comAddress,
room=buildingID),
headers=headers,
data=payload)
df = df.append(pd.DataFrame(json.loads(response.text)['data']),ignore_index=True)
df["日结算用量"]=df["日结算用量"].astype('float')
df["日结算金额"]=df["日结算金额"].astype('float')
df.to_stata(piplineName+'电量电费'+".dta",version=118,write_index=False)
print(piplineName+' finished')
return df
4. 运行效果
运行如下命令:
up_to_now = list(range(202208,202213))+list(range(202301,202313))+list(range(202401,202304))
data_v_f = crawl_electric_vol_fare(up_to_now,'XX','XX') # 脱敏
data_v_f.loc[:,['日结算用量','日结算金额']].plot()
横轴表示从2022年8月份开学至今的天数,365天为一年。可以发现,开学初的几个月,也就是0-100天这段时间,正值广东最热的时候,电量电费均呈现“双高” 。类似的“双高”情况也出现开学的300-350天左右,也是夏天。在200天和400天之前的一段时间,电费电量基本为零,这是因为学生们放寒假回家,宿舍没有人了。
总得来说,还是很有意思的哈哈哈。