【python】科技与狠活!带你爬取小程序上的电量电价

1. motivation

随着气温回升,南方已进入到需要靠着冷空调度日的季节了。最近宿舍电费“蹭蹭蹭”地往上涨,宿舍舍友轮番充值了许多次。为了搞清楚自己宿舍每日用电的情况,笔者从我校充值小程序上爬取了本人宿舍自开学来的用电情况。出于隐私保护的目的,本文仅展示爬取思路和核心代码,cookie、header、url等核心信息,恕不展示。

2. 如何从小程序上爬取数据?

小程序不同于网页。网页在地址栏有显性的网址和明确的请求方式(get或post),而小程序的网址和请求方式相对隐性,但并不意味着没有!这时,我们就需要借助抓包软件进行辅助操作。笔者偏好于使用 fiddler+SwitchyOmega 的组合,对小程序进行抓包。

由于本文初衷是展示思路,不过多讲解技术上的操作。感兴趣的读者,可自行查阅相关操作方法。日后如有时间,笔者会专门写一篇文章,讲解 fiddler和SwitchyOmega的下载与配置,以及它们的使用技巧。

参考资料:

Fiddler安装和配置_fiddler配置-CSDN博客

安装 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天之前的一段时间,电费电量基本为零,这是因为学生们放寒假回家,宿舍没有人了。

总得来说,还是很有意思的哈哈哈。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值