利用云函数使用预约图书馆脚本

2022/3/17 · 2 min read

一、代码及配置文件

1. 代码

```python
# -*- coding: utf8 -*-
import json
import requests
import re
import datetime

session = requests.session()
header = {
    # 设定报文头
    'Host': 'libzwxt.ahnu.edu.cn',
    'Origin': 'http://libzwxt.ahnu.edu.cn',
    'Referer': 'http://libzwxt.ahnu.edu.cn/SeatWx/Seat.aspx?fid=1&sid=1',
    'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
    'X-AjaxPro-Method': 'AddOrder',
}

def getTime(st: int, et: int) -> any:
    st = '0' + str(st) if st < 10 else st
    et = '0' + str(et) if et < 10 else et
    return {
        'st': f'{st}:00',
        'et': f'{et}:00'
    }


def getDateTimeSection(times, sid: str) -> dict:
    tomorrow = (datetime.datetime.now() + datetime.timedelta(days=+1, hours=+8))
    week = tomorrow.weekday()
    at_date = tomorrow.strftime("%Y-%m-%d")
    times = getTime(times[week]['st'], times[week]['et'])
    return {
        'atDate': at_date,
        'st': at_date + ' ' + times['st'],
        'et': at_date + ' ' + times['et'],
        'sid': sid,
    }


# 获取登陆页面内容
def getLoginPageContent() -> str:
    return session.get('https://libzwxt.ahnu.edu.cn/SeatWx/login.aspx').text


# 获取登陆所需字段
def getLoginPostData(login_page_content: str) -> dict:
    login_post_data = {
        'Button1': '登 录  ',
        'hfurl': ''
    }
    params_name_list = ['__VIEWSTATE', '__VIEWSTATEGENERATOR', '__EVENTVALIDATION']
    for param_name in params_name_list:
        param_regex = re.compile(rf'id=\"{param_name}\" value=\".+\"')
        ret = param_regex.search(login_page_content)
        param_value = ret.group()
        login_post_data[param_name] = param_value.split("\"")[3]

    return login_post_data

# 登陆
def login(tb_user_name: str, tb_pass_word: str) -> None:
    login_page_content = getLoginPageContent()
    login_post_data = getLoginPostData(login_page_content)
    login_post_data["tbUserName"] = tb_user_name
    login_post_data["tbPassWord"] = tb_pass_word
    ret = session.post('https://libzwxt.ahnu.edu.cn/SeatWx/login.aspx', login_post_data).text

# 预约
def reserve(sid: str, email: str, times) -> None:
    reserve_post_data = getDateTimeSection(times, sid)
    print(reserve_post_data)
    ret = session.post('https://libzwxt.ahnu.edu.cn/SeatWx/ajaxpro/SeatManage.Seat,SeatManage.ashx',
                    data=json.dumps(reserve_post_data), headers=header).text
    sendEmail(ret + str(reserve_post_data), email)

def isValidSeat(sid: str) -> bool: 
    ret = session.post('https://libzwxt.ahnu.edu.cn/SeatWx/Room.aspx?rid=1&fid=1', headers=header).text
    t = f"href=''>nbk{sid}"
    res = ret.find(f"href=''>nbk{sid}")
    return res == -1

def sendEmail(message: str, email: str) -> str:
    print(message)
    data = {
        'receiver': email,
        'title': '图书馆预约通知',
        'content': message
    }
    print('发送邮件...')
    ret = requests.post('http://api.mayapony.site/mailer', data=data).text
    return ret

def run() -> None:
    print('开始预约!')
    # noinspection PyBroadException
    with open('config.json', 'r') as f:
        config = json.load(f)
        sid = config.get('sid')
        email = config.get('email')
        username = config.get('username')
        password = config.get('password')
        times = config.get('times')
        try:
            login(username, password)
            print('登陆成功,正在预定...')
            if isValidSeat(sid):
                reserve(sid, email, times)
            else:
                reserve(str(int(sid) - 1), email, times)
        except Exception as e:
            print(e);
            sendEmail('出错!' + str(e), email)
        print('执行完毕!')

def main_handler(event, context):
    run()

if __name__ == '__main__':
    run()
```

2. 配置文件

  • username: 用户名
  • password: 密码
  • sid: 座位后面的数字
  • emails: 接受邮件的邮箱
  • times: 周一至周日的预约时间,时间格式为整点,st为开始时间,et为结束时间
{
  "username": "xxx",
  "password": "xxx",
  "sid": "221",
  "email": "xxx@xxx",
  "times": [
    {
      "st": 9,
      "et": 21
    },
    {
      "st": 14,
      "et": 21
    },
    {
      "st": 14,
      "et": 21
    },
    {
      "st": 9,
      "et": 21
    },
    {
      "st": 17,
      "et": 21
    },
    {
      "st": 9,
      "et": 21
    },
    {
      "st": 9,
      "et": 21
    }
  ]
}

二、代码放到腾讯云函数

云函数地址

1. 新建云函数

建议区域选择上海

2. 放入代码

python版本选择3.6,因为腾讯云函数对3.6版本支持比较好,提供常用的包 (本代码所需的都有)。并且提供更好用的在线编辑器。

然后把代码粘贴进编辑器

同理新建config.json把配置文件也放进去

设置触发器

最后点完成就行了。