bear-zd / ChaoXingReserveSeat

超星学习通图书馆抢座脚本
75 stars 84 forks source link

一次运行,多次预约 #38

Closed Raudience closed 1 month ago

Raudience commented 1 month ago

因为本校座位预约一次只能预约3小时,所以一天需要进行三次不同时间段的预约,所以希望预约时间段也能多选,一次运行,多次预约

Raudience commented 1 month ago

就像这样,另外考虑适配青龙面板吗,青龙真的很好用image

bear-zd commented 1 month ago

在utils/reserve.py get_submit函数加个判断就好了,用list或者tuple看个人了:

    def get_submit(self, url, times, token, roomid, seatid, captcha="", action=False):
        delta_day = 1 if self.reserve_next_day else 0
        day = datetime.date.today() + datetime.timedelta(days=0+delta_day)  # 预约今天,修改days=1表示预约明天
        if action:
            day = datetime.date.today() + datetime.timedelta(days=1+delta_day)  # 由于action时区问题导致其早+8区一天
        if isinstance(times, list):
            for t in times:
                parm = {
                    "roomId": roomid,
                    "startTime": t[0],
                    "endTime": t[1],
                    "day": str(day),
                    "seatNum": seatid,
                    "captcha": captcha,
                    "token": token
                }
                logging.info(f"submit parameter {parm} ")
                parm["enc"] = enc(parm)
                html = self.requests.post(
                    url=url, params=parm, verify=True).content.decode('utf-8')
                self.submit_msg.append(
                    times[0] + "~" + times[1] + ':  ' + str(json.loads(html)))
                logging.info(json.loads(html))
        else:
            parm = {
                    "roomId": roomid,
                    "startTime": times[0],
                    "endTime": times[1],
                    "day": str(day),
                    "seatNum": seatid,
                    "captcha": captcha,
                    "token": token
                }
            logging.info(f"submit parameter {parm} ")
            parm["enc"] = enc(parm)
            html = self.requests.post(
                url=url, params=parm, verify=True).content.decode('utf-8')
            self.submit_msg.append(
                times[0] + "~" + times[1] + ':  ' + str(json.loads(html)))
            logging.info(json.loads(html))

        return json.loads(html)["success"]

至于青龙面板的话我看好像写脚本就好了,用crontab应该是同样的效果,至于远程控制、微信通知这些这个项目就不折腾了。

GccEzz commented 1 month ago

在utils/reserve.py get_submit函数加个判断就好了,用list或者tuple看个人了:

    def get_submit(self, url, times, token, roomid, seatid, captcha="", action=False):
        delta_day = 1 if self.reserve_next_day else 0
        day = datetime.date.today() + datetime.timedelta(days=0+delta_day)  # 预约今天,修改days=1表示预约明天
        if action:
            day = datetime.date.today() + datetime.timedelta(days=1+delta_day)  # 由于action时区问题导致其早+8区一天
        if isinstance(times, list):
            for t in times:
                parm = {
                    "roomId": roomid,
                    "startTime": t[0],
                    "endTime": t[1],
                    "day": str(day),
                    "seatNum": seatid,
                    "captcha": captcha,
                    "token": token
                }
                logging.info(f"submit parameter {parm} ")
                parm["enc"] = enc(parm)
                html = self.requests.post(
                    url=url, params=parm, verify=True).content.decode('utf-8')
                self.submit_msg.append(
                    times[0] + "~" + times[1] + ':  ' + str(json.loads(html)))
                logging.info(json.loads(html))
        else:
            parm = {
                    "roomId": roomid,
                    "startTime": times[0],
                    "endTime": times[1],
                    "day": str(day),
                    "seatNum": seatid,
                    "captcha": captcha,
                    "token": token
                }
            logging.info(f"submit parameter {parm} ")
            parm["enc"] = enc(parm)
            html = self.requests.post(
                url=url, params=parm, verify=True).content.decode('utf-8')
            self.submit_msg.append(
                times[0] + "~" + times[1] + ':  ' + str(json.loads(html)))
            logging.info(json.loads(html))

        return json.loads(html)["success"]

至于青龙面板的话我看好像写脚本就好了,用crontab应该是同样的效果,至于远程控制、微信通知这些这个项目就不折腾了。

老哥,这样改它显示保存失败。日志显示starttime和entime为0和1。另外想问一下他这个座位预约是不是不同时段对应多个token?还是一个token可以约三个时段呢?如果是一个时段一个token的话这里是否需要每次循环那个时间段的时候获取一次新的token for t in times:

每次提交前获取新的 token

        token = self.get_token()
                        ...

目前好像是一次登录获取一个token,能否只登录一次然后保存登陆信息,后续只提交预约座位信息而不重新登陆呢?

bear-zd commented 1 month ago

登陆一次可以预约多次这个没问题,登陆的相关信息保存在self.requests的cookies里面了,但是要想预约的话每次还是需要计算token和对应的captcha(如果有的话),那试试修改submit函数吧:

    def submit(self, times, roomid, seatid, action):
        for seat in seatid:
            suc = False
            if isinstance(times[0], str):
                while not suc and self.max_attempt > 0:
                    token = self._get_page_token(self.url.format(roomid, seat))
                    logging.info(f"Get token: {token}")
                    captcha = self.resolve_captcha() if self.enable_slider else "" 
                    logging.info(f"Captcha token {captcha}")
                    suc = self.get_submit(self.submit_url, times=times,token=token, roomid=roomid, seatid=seat, captcha=captcha, action=action)
                    if suc:
                        return suc
                    time.sleep(self.sleep_time)
                    self.max_attempt -= 1
                return suc
            else:
                times_suc = 0

                while times_suc < len(times) and self.max_attempt > 0:
                    for time in times:
                        token = self._get_page_token(self.url.format(roomid, seat))
                        logging.info(f"Get token: {token}")
                        captcha = self.resolve_captcha() if self.enable_slider else "" 
                        logging.info(f"Captcha token {captcha}")
                        suc = self.get_submit(self.submit_url, times=time,token=token, roomid=roomid, seatid=seat, captcha=captcha, action=action)
                        if suc:
                            times_suc +=1
                        time.sleep(self.sleep_time)

                    self.max_attempt -= 1
                return times_suc == len(times)

因为这种算是排列组合的一种修改,对整体好像即使是多次登陆多次预约影响差异也不大(或者你起多线程预约),因为不算特别通用的功能就不commit到公共分支了

GccEzz commented 1 month ago

登陆一次可以预约多次这个没问题,登陆的相关信息保存在self.requests的cookies里面了,但是要想预约的话每次还是需要计算token和对应的captcha(如果有的话),那试试修改submit函数吧:

    def submit(self, times, roomid, seatid, action):
        for seat in seatid:
            suc = False
            if isinstance(times[0], str):
                while not suc and self.max_attempt > 0:
                    token = self._get_page_token(self.url.format(roomid, seat))
                    logging.info(f"Get token: {token}")
                    captcha = self.resolve_captcha() if self.enable_slider else "" 
                    logging.info(f"Captcha token {captcha}")
                    suc = self.get_submit(self.submit_url, times=times,token=token, roomid=roomid, seatid=seat, captcha=captcha, action=action)
                    if suc:
                        return suc
                    time.sleep(self.sleep_time)
                    self.max_attempt -= 1
                return suc
            else:
                times_suc = 0

                while times_suc < len(times) and self.max_attempt > 0:
                    for time in times:
                        token = self._get_page_token(self.url.format(roomid, seat))
                        logging.info(f"Get token: {token}")
                        captcha = self.resolve_captcha() if self.enable_slider else "" 
                        logging.info(f"Captcha token {captcha}")
                        suc = self.get_submit(self.submit_url, times=time,token=token, roomid=roomid, seatid=seat, captcha=captcha, action=action)
                        if suc:
                            times_suc +=1
                        time.sleep(self.sleep_time)

                    self.max_attempt -= 1
                return times_suc == len(times)

因为这种算是排列组合的一种修改,对整体好像即使是多次登陆多次预约影响差异也不大(或者你起多线程预约),因为不算特别通用的功能就不commit到公共分支了

好的好的