返回
Featured image of post Python - 用Selenium抢体育场地

Python - 用Selenium抢体育场地

最近学校运动场预约网站登上去都难,别说抢场地了,赶紧弄个脚本帮忙抢

学校用来预约场地的服务器实在承载能力有限。八点钟登上去,起码要八点零五才能第一次刷新成功,加上一般就开放五六片场地,根本不可能抢不到

那么,就只能用科技对付科技了,也好让我早上多睡会好歹脚本抢不到没有拼手速被服务器gank那么气

一、安装Chrome

先将Chrome RPM包下载下来

wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

安装两个依赖包

yum install -y lsb
yum install -y libXScrnSaver

从已下载到本地的RPM包安装Chrome

yum localinstall -y google-chrome-stable_current_x86_64.rpm

2022年六月,安装的版本是102.0.5005.61


二、安装chromedriver

从淘宝镜像库找对应Chrome版本的驱动 http://npm.taobao.org/mirrors/chromedriver/

wget https://registry.npmmirror.com/-/binary/chromedriver/102.0.5005.61/chromedriver_linux64.zip
unzip chromedriver_linux64.zip
mv chromedriver /usr/bin/
chromedriver --version

只提供了zip包,如果系统没有装unzip zip的话一并装了就行了yum install -y unzip zip

最后通过chromedriver --version验证安装版本


三、安装Python3

Centos7本身是有Python2.7的,但是因为yum依赖于Python2.7,直接卸载旧版本换新的会有很多问题所以还是比较建议装新版本时候软链接用/usr/bin/python3而不是直接写python,毕竟python本身就存在2和3不兼容问题,好区分一点

  1. 安装依赖

    yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc* make -y
    
  2. 下载安装包

    wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tar.xz
    
  3. 解压

    tar -Jxvf Python-3.8.10.tar.xz
    
  4. 配置安装路径

    cd Python-3.8.10
    ./configure prefix=/usr/local/python3
    
  5. 编译安装

    make && make install
    
  6. 配置软连接

    ln -s /usr/local/python3/bin/python3 /usr/bin/python3
    ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
    
  7. 安装pip

    wget py		# 下载
    python3 get-pip.py													# 安装
    pip -V
    

pip3在linux上一个个添依赖是比较麻烦的事情,如果在Windows上有比较完整的依赖,可以直接dump一个依赖列表到服务器上,让pip自动添加

#	在Windows上CMD
cd Desktop
pip freeze > packages.txt

如果Python版本不同强烈不建议这么搞,很容易发生版本对不上问题

然后到Centos上进行pip3

pip3 install -r packages.txt

当然如果只需要Selenium,直接装就行了

pip3 install selenium

四、chrome_options

使用selenium调用chromedriver也并不顺利,以下是Centos7配合上述Chrome版本,实际可用的一套设置

chrome_options = Options()
chrome_options.add_argument('--headless')  # 无界面
chrome_options.add_argument('--no-sandbox')  # 解决DevToolsActivePort文件不存在报错问题
chrome_options.add_argument('--disable-gpu')   # 禁用GPU硬件加速。如果软件渲染器没有就位,则GPU进程将不会启动。
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',chrome_options=chrome_options)

五、定时任务

因为是一个预约球场的脚本,每天系统开放时间是早上八点,那么我们用定时任务让脚本在七点五十九跑起来Centos7下默认安装有crontab,如果没有也可以直接yum yum install crontabs

crontab -e		# 编辑定时任务,会以vim的形式编辑
# 在文档里加一条定时任务,每天的7点59分执行,注意用绝对路径
59 7 * * * /usr/bin/python3 /usr/local/reserve/reserve.py

接下来重启一下crontab服务

service crond restart

再查看一下当前系统的定时任务列表

crontab -l

没有问题的话,就大功告成了


六、顺便贴一下脚本代码

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests
import datetime
import ddddocr
import sys


class Logger(object):
    def __init__(self, filename='default.log', stream=sys.stdout):
        self.terminal = stream
        self.log = open(filename, 'a')

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

    def flush(self):
        pass


myheaders = {
    "Accept": "text/plain, */*; q=0.01",
    "Accept-Encoding": "br, gzip, deflate",
    "Accept-Language": "zh-cn",
    "Host": "yuyue.seu.edu.cn",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
}
myurl = "http://yuyue.seu.edu.cn/eduplus/order/order/order/judgeUseUser.do?sclId=1"
logfile = 'default.log'


def wait_element_click(driver, wait, path):
    wait.until(EC.element_to_be_clickable((By.XPATH, path)))
    driver.find_element_by_xpath(path).click()


def request_check_code(r):
    ocr = ddddocr.DdddOcr(show_ad=False)
    return ocr.classification(r.content)


def login(uid, pwd):
    # chromedriver_autoinstaller.install()
    chrome_options = webdriver.ChromeOptions()
    # 指定chrome启动类型为headless 并且禁用gpu
    chrome_options.add_argument('--headless')  # 无界面
    chrome_options.add_argument('--no-sandbox')  # 解决DevToolsActivePort文件不存在报错问题
    chrome_options.add_argument('--disable-gpu')   # 禁用GPU硬件加速。如果软件渲染器没有就位,则GPU进程将不会启动。
    chrome_options.add_argument('--disable-dev-shm-usage')
    driver = webdriver.Chrome(options=chrome_options)
    driver.get("http://yuyue.seu.edu.cn/eduplus/order/initOrderIndex.do?sclId=1")
    driver.find_element_by_xpath("//div[@class='auth_tab_content']/div[1]/form/p[1]/input").send_keys(uid)
    driver.find_element_by_xpath("//div[@class='auth_tab_content']/div[1]/form/p[2]/input").send_keys(pwd)
    driver.find_element_by_xpath("//div[@class='auth_tab_content']/div[1]/form/p[5]/button").click()
    wait = WebDriverWait(driver, 2, 0.5)
    try:
        alert = driver.switch_to.alert  # 切换到弹窗
        # print("alert: " + alert.text)  # 打印弹窗显示的信息:Alert Message
        alert.accept()
    except:
        # print("no alert")
        pass
    driver_cookies = driver.get_cookies()
    c = {c['name']: c['value'] for c in driver_cookies}
    driver.close()
    return c


def reserve(user):
    uid = user["uid"]
    pwd = user["pwd"]
    target_time = user["target_time"]
    target_weight = user["target_weight"]
    name = user["name"]
    phone = user["phone"]
    c = login(uid, pwd)
    # r=requests.post(url,headers=myheaders,params=payload,cookies=c)
    image_url = "http://yuyue.seu.edu.cn/eduplus/validateimage"
    r = requests.get(image_url, headers=myheaders, cookies=c)
    vc = ""
    vc = request_check_code(r)
    print(vc)
    url_judge = "http://yuyue.seu.edu.cn/eduplus/order/order/order/judgeUseUser.do?sclId=1"
    """itemId
        羽毛球 10
        乒乓球 7
    """
    payload_judges = []
    date_time = (datetime.date.today() + datetime.timedelta(days=2)).strftime("%Y-%m-%d")
    for time, weight in zip(target_time, target_weight):
        order_time = date_time + " " + time
        print(order_time + " " + name)
        payload_judge = {"ids": "", "useTime": order_time, "phone": phone, "remark": "", "itemId": "10",
                         "allowHalf": "2",
                         "validateCode": vc}
        for i in range(int(10 * weight + 0.5)):
            payload_judges.append(payload_judge)
    """ First Touch
    """
    try:
        r = requests.post(url_judge, params=payload_judges[0], headers=myheaders, cookies=c)
    except:
        pass
    print(r.text)
    while r.text.find("code") >= 0:
        print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '' + "get new code------------")
        r = requests.get(image_url, headers=myheaders, cookies=c)
        vc = request_check_code(r)
        payload_judges[0]["validateCode"] = vc
        r = requests.post(url_judge, params=payload_judges[0], headers=myheaders, cookies=c)
        print(vc)
    i = 0
    print('\n' + r.text)
    current_target = payload_judges[0]["useTime"]
    """ Repeat
    """
    while r.text.find("error") >= 0 and i < 200:
        for payload_judge in payload_judges:
            if payload_judge["useTime"] == current_target:
                payload_judge["validateCode"] = vc
            else:
                r = requests.get(image_url, headers=myheaders, cookies=c)
                payload_judge["validateCode"] = request_check_code(r)
            r = requests.post(url_judge, params=payload_judge, headers=myheaders, cookies=c)
            print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '' + payload_judge["useTime"] + ' ' + r.text)

            while r.text.find("code") >= 0:
                print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + '' + "get new code------------")
                r = requests.get(image_url, headers=myheaders, cookies=c)
                vc = request_check_code(r)
                payload_judge["validateCode"] = vc
                r = requests.post(url_judge, params=payload_judge, headers=myheaders, cookies=c)
                print(vc)
        i = i + 1
    if i == 200:
        print(name + "failed" + "  i=" + str(i))
    else:
        print(name + "success" + "  i=" + str(i))


if __name__ == "__main__":
    sys.stdout = Logger(logfile, sys.stdout)
    sys.stderr = Logger(logfile, sys.stderr)  # redirect std err, if necessary

    user = {
        "uid": "#{一卡通号}",
        "pwd": "#{一卡通号}",
      	# 因为每天开放时间段都不一样,可以定几个时间按请求比例抢
        "target_time": ("16:00-17:00", "15:00-16:00", "17:00-18:00", "18:00-19:00", "19:00-20:00"),
        "target_weight": (0.5, 0.15, 0.15, 0.1, 0.1),
        "name": "#{姓名,写啥都行}",
        "phone": "#{手机号,也是写啥都行}"
    }
    reserve(user)
  • 稍微优化了一下,可以几个时间段一起抢
  • 输出日志,没抢到可以看到原因

第二天早上起来一看

YES!

好吧,其实这是一周里唯一一次成功抢到的,靠的还是学校大发慈悲放了四片场地

comments powered by Disqus