图书馆预约小工具

2022/3/15 · 2 min read

代码

#!/usr/bin/env python3
import json
import requests
import re
import datetime
from typing import TypedDict

MayaTime = TypedDict('MayaTime', {'st': str, 'et': str})
session = requests.session()
sid = 223   # 座位号


# 获取起止时间字典
def getTime(st: int, et: int) -> MayaTime:
    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() -> any:
    times = [getTime(9, 21), getTime(14, 21), getTime(14, 21), getTime(9, 21), getTime(17, 21),
             getTime(9, 21), getTime(9, 21)]
    tomorrow = (datetime.datetime.now() + datetime.timedelta(days=+1))
    week = tomorrow.weekday()
    at_date = tomorrow.strftime("%Y-%m-%d")
    return {
        'atDate': at_date,
        'st': at_date + ' ' + times[week].get('st'),
        'et': at_date + ' ' + times[week].get('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() -> None:
    reserve_post_data = getDateTimeSection()
    header = {
        # 设定报文头
        'Host': 'libzwxt.ahnu.edu.cn',
        'Origin': 'http://libzwxt.ahnu.edu.cn',
        'Referer': 'http://libzwxt.ahnu.edu.cn/SeatWx/Seat.aspx?fid=3&sid=1438',
        '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',
    }
    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)


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


if __name__ == '__main__':
    print('开始预约!')
    # noinspection PyBroadException
    try:
        login('帐号', '密码')
        print('登陆成功,正在预定...')
        reserve()
    except Exception as e:
        sendEmail('出错!')
    print('执行完毕!')

使用

  • python 代码文件放到服务器上,使用shell脚本执行(方便后期使用crontab进行定时执行)

    python3 /path/to/index.py
    

    使用 chmod +x /path/to/shellName.sh 使脚本可执行。

  • 或者在 python 文件头部添加注释 #!/usr/bin/env python3,并使用 chmod 使其可执行即可。

安装 Python3.8

在放到服务器上执行报错:

ImportError: cannot import name 'TypedDict'

这是因为 TypedDict 仅支持 python3.8 之后的版本,需要进行安装。

  1. 下载 python 包:

    wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz

  2. 解压

    xz -d Python-3.8.2.tar.xz
    

    xz 是一个压缩工具

    参数说明:

    -z, --compress    # 强制压缩
    -d, --decompress, --uncompress
                      # 强制解压
    -t, --test        # 测试压缩文件的完整性
    -l, --list        # 列出有关.xz文件的信息
    -k, --keep        # 保留(不要删除)输入文件
    -f, --force       # 强制覆盖输出文件和(解)压缩链接
    -c, --stdout, --to-stdout
                      # 写入标准输出,不要删除输入文件
    -0 ... -9         # 压缩预设; 默认为6; 取压缩机*和*
                      # 使用7-9之前解压缩内存使用量考虑在内!
    -e, --extreme     # 尝试通过使用更多的CPU时间来提高压缩比;
                      # 要求不影响解压缩存储器
    -T, --threads=NUM # 最多使用NUM个线程; 默认值为1;  set to 0
                      # 设置为0,使用与处理器内核一样多的线程
    -q, --quiet       # 抑制警告; 指定两次以抑制错误
    -v, --verbose     # 冗长; 指定两次更详细
    -h, --help        # 显示这个简洁的帮助并退出
    -H, --long-help   # 显示更多帮助(还列出了高级选项)
    -V, --version     # 显示版本号并退出
    
  3. 安装:

    cd Python-3.8.2
    # 安装目录
    ./configure --prefix=/usr/local/python3
    # 编译
    make
    # 编译安装
    make install
    # 建立软链接
    ln -s /usr/local/python3/bin/python3.8 /usr/bin/python
    ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
    

    OK!

装好了,迫不及待执行 python index.py 进行测试,结果发现无法请求图书馆接口!!,尝试 ping 图书馆域名也不通,果断放弃暂时先在自己电脑上跑着吧。

设置定时

crontab -e

在打开的buffer里添加:

10 6 * * * /path/to/index.py 意思是每天的六点十分执行。美滋滋