def rk_create(self, im_string, timeout=60): """ im: 图片字节 im_type: 题目类型 """ params = { 'typeid': 6113, 'timeout': timeout, } params.update(self.base_params) files = {'image': ('a.jpg', im_string)} while True: try: r = requests.post('http://api.ruokuai.com/create.json', data=params, files=files, headers=self.headers) # Log.v("使用若快进行验证码识别") data = r.json() break except requests.RequestException: Log.w("提交若快打码请求出现问题, 正在重试中...") continue Log.d(data) return data
def send_email(msg_type, **extra_var): """ 邮件通知 :param msg_type: email content type id. in EMAIL_MESSAGE dict. :param extra_var: format content var dict. :return: """ email_conf = Config.email_config if not Config.email_notice_enable: Log.v("未开启邮箱通知") else: data = EMAIL_MESSAGES[msg_type] try: sender = email_conf.from_email receiver = email_conf.notice_email_list subject = data["subject"] username = email_conf.username password = email_conf.password host = email_conf.email_gateway port = email_conf.email_port s = data["content"].format(**extra_var) msg = MIMEText(s, 'html', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = sender msg['To'] = ','.join(receiver) print(host, port) smtp = smtplib.SMTP(host) smtp.connect(host, port=port) smtp.login(username, password) smtp.send_message(msg) smtp.quit() Log.v("邮件发送成功") except Exception as e: Log.e("发送失败, 邮件配置有误, 请检查配置")
def login(self): self._init() captcha = Captcha("normal") status, msg = captcha.verify() if not status: Log.v("验证码校验失败") return status, msg payload = { 'username': Config.train_account.user, 'password': Config.train_account.pwd, 'appid': 'otn', 'answer': captcha.results } json_response = send_requests(LOGIN_SESSION, self.URLS['login'], data=payload) result, msg = json_status(json_response, [], '0') if not result: return False, msg self._passportredirect() result, msg, apptk = self._uamtk() if not result: Log.v(msg) return False, msg status, msg = self._uamauthclient(apptk) return status, msg
def _get_queue_count(self): form_data = { 'train_date': datetime.datetime.strptime( self.ticket_passenger_info['queryLeftTicketRequestDTO']['train_date'], '%Y%m%d').strftime( '%b %a %d %Y 00:00:00 GMT+0800') + ' (中国标准时间)', 'train_no': self.ticket_passenger_info['queryLeftTicketRequestDTO']['train_no'], 'stationTrainCode': self.train.stationTrainCode.value, 'seatType': self.seat_type.sys_code, 'fromStationTelecode': self.train.from_station_code.value, 'toStationTelecode': self.train.to_station_code.value, 'leftTicket': self.ticket_passenger_info['leftTicketStr'], 'purpose_codes': self.ticket_passenger_info['purpose_codes'], 'train_location': self.ticket_passenger_info['train_location'], '_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token } Log.v("正在获取排队信息以及余票信息中...") json_response = send_requests(LOGIN_SESSION, self.URLS['getQueueCount'], data=form_data) status, msg = submit_response_checker(json_response, ["status"], True, "获取余票信息成功") if status: self.left_tickets = json_response['data']['ticket'] Log.v("票数剩余{0}张, 排队人数为{1}人".format( self.left_tickets, json_response['data']['count'] )) else: BlackTrains.add_train(self.train) return status, msg
def _submit_order_request(self): """ :return: """ form_data = { 'secretStr': self.decode_secret_str(self.train.secretStr.value), 'train_date': self.format_date(self.train.train_date.value), # 车票时间 'back_train_date': time.strftime("%Y-%m-%d", time.localtime()), # query date:2017-12-31 'tour_flag': 'dc', 'purpose_codes': find_by_name("ticket", Config.basic_config.ticket_type).sys_code, 'query_from_station_name': self.train.from_station.value.name, 'query_to_station_name': self.train.to_station.value.name, 'undefined': '', } Log.v("请求预提交订单") json_response = send_requests(LOGIN_SESSION, self.URLS['submitOrderRequest'], data=form_data) return submit_response_checker(json_response, ["status"], True, "请求预提交订单成功")
def filter_black_trains(self): result = [] for v in self.result: flag = BlackTrains.check(v[1]) if flag: Log.v("{0} 车次已经在小黑屋".format(v[1].stationTrainCode.value)) else: result.append(copy.copy(v)) return result
def online_checker_now(self): status, msg = OnlineCheckerTool.checker() OnlineCheckerTool.update_check_time() if not status: Log.v("用户登录失效, 正在为您重试登录") login_status = self.login() if not login_status: return False, "重试登录失败" else: return status, msg
def _check_order_status_queue(self): params = { 'orderSequence_no': self.order_id, '_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token, } Log.v("检查已提交的订单的状态中...") json_response = send_requests(LOGIN_SESSION, self.URLS['resultOrderForQueue'], params=params) status, msg = submit_response_checker(json_response, ["status", "data.submitStatus"], True, "订单已经成功提交") return status, msg
def getcaptcha(): while True: try: data = get_captcha_image( LOGIN_SESSION, LOGIN_URL_MAPPING["normal"]["captcha"]) break except ResponseCodeError: Log.v("获取验证码信息失败,重试获取验证码中...") continue img_binary = base64.b64decode(data["image"]) return img_binary
def run(self, travel_date): Log.v("当前查询日期为 {}".format(travel_date)) q = Query(travel_date) data = q.filter() if not data: Log.v("日期 {0} 满足条件的车次暂无余票, 正在重新查询".format(travel_date)) for v in data: print("\t\t\t当前座位席别 {}".format(v[0].name)) q.pretty_output(v[1]) return data
def run(self): while self.retry_time: for v in NORMAL_PIPELINE: status, msg = getattr(self, v)() if not status: self.retry_time -= 1 break else: Log.v("提交订单成功") return True Log.v("提交订单失败") return False
def filter(self): # 先过滤席位 self.filter_by_seat() if self.result: Log.v("查找到符合配置的车次信息: {0}".format(','.join( [v[1].stationTrainCode.value for v in self.result]))) if Config.basic_config.manual_trainnum_enable: self.result = self.filter_train_num() else: self.result = self.filter_train_time() self.result = self.filter_train_type() return self.result
def verifyhandle_hand(self): img = Image.open(BytesIO(self.generator_image())) img.show() Log.v(""" ----------------- | 0 | 1 | 2 | 3 | ----------------- | 4 | 5 | 6 | 7 | ----------------- """) results = input("输入验证码索引(见上图,以','分割): ") img.close() trans = self.trans_captcha_results(results) self.results = trans return self.check(trans)
def online_checker(self): # 两分钟检测一次 flag = OnlineCheckerTool.should_check_online(datetime.datetime.now()) if flag: status, msg = OnlineCheckerTool.checker() OnlineCheckerTool.update_check_time() if not status: Log.v("用户登录失效, 正在为您重试登录") l = self.login() if not l: return False, "重试登录失败" else: return status, msg else: status, msg = True, "用户状态检测:未到检测时间" return status, msg
def check_current_mode(self): if (not Config.presale_enable) or self.pre_sale_end: return False else: now = datetime.datetime.now() open_times = list(map(format_time, Config.presale_config.start_times)) f = lambda x: x - now <= self.delta_stop_time and now - x <= self.delta_continue_time result = any(filter(f, open_times)) if result: Log.v("当前处于预售模式,不再处理正常模式下的日期查询") return True check_result = list(filter(lambda x: now > x + self.delta_continue_time, open_times)) if check_result and all(check_result): self.pre_sale_end = True return False return False
def raw_data(self): while True: try: r = requests.get(STATION_URL) if r.status_code == requests.codes.ok: raw_data = city_re.findall(r.text) if raw_data: # remove empty line data. data = map(lambda x: x.strip(), raw_data[0].split("@")) Log.v("获取车站信息成功") return list(filter(lambda x: bool(x), data)) else: Log.w("无法读取车站信息,重试中") continue except requests.RequestException: Log.w("获取车站信息失败,重试获取中") continue
def _check_order_info(self): form_data = { 'cancel_flag': self.ticket_passenger_info['orderRequestDTO']['cancel_flag'] or '2', 'bed_level_order_num': self.ticket_passenger_info['orderRequestDTO']['bed_level_order_num'] \ or '000000000000000000000000000000', 'passengerTicketStr': build_passenger_ticket_string(self.seat_type, self.passenger_data), 'oldPassengerStr': build_oldpassenger_ticket_string(self.passenger_data), 'tour_flag': self.ticket_passenger_info['tour_flag'] or 'dc', 'randCode': '', 'whatsSelect': '1', '_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token, } Log.v("正在提交检查订单状态请求") json_response = send_requests(LOGIN_SESSION, self.URLS['checkOrderInfo'], data=form_data) status, msg = submit_response_checker(json_response, ["status", "data.submitStatus"], True, "校验订单成功") return status, msg
def check(self, results): form_data = { 'randCode': results, 'rand': 'sjrand', } json_response = send_requests( LOGIN_SESSION, LOGIN_URL_MAPPING["other"]["captchaCheck"], data=form_data) Log.v('other login captcha verify: %s' % json_response) def verify(response): return response['status'] and self.success_code == response[ 'data']['result'] v = verify(json_response) return v, "Error" if not v else v, "ok"
def _get_submit_token(self): html = send_requests(LOGIN_SESSION, self.URLS['getExtraInfo']) Log.v("获取token中....") result = re.findall(r"var globalRepeatSubmitToken = '(.*)'", html) ticket_passenger_info = re.findall(r'var ticketInfoForPassengerForm=(.*);', html) if result: self.token = result[0] if ticket_passenger_info: try: self.ticket_passenger_info = json.loads(ticket_passenger_info[0].replace("'", "\"")) except TypeError: Log.w("获取submit info失败") return False if self.token and self.ticket_passenger_info: Log.v("成功获取token与以及车次信息") return True else: return False
def _wait_for_order_id(self): # 排队逻辑 t = datetime.datetime.now() delta = datetime.timedelta(minutes=10) while self.wait_time and self.wait_time >= 0: loop_time = datetime.datetime.now() status, msg = self._query_order_wait_time() Log.v(msg) s, data = find_by_phrase(msg) if s: self.break_submit, self.break_msg = False, data["msg"] return self.break_submit, self.break_msg time.sleep(5) if self.order_id: return True, "OK" if loop_time > t + delta: return False, "提交超时" return False, "排队失败"
def run(self): while self.retry_time: for v in NORMAL_PIPELINE: status, msg = getattr(self, v)() if self.break_submit: self.retry_time = 0 Log.v(self.break_msg) break Log.v(msg) if not status: self.retry_time -= 1 break else: Log.v("提交订单成功, 订单号为 {0}, 请登录12036在30分钟内完成支付".format( self.order_id)) return True Log.v("提交订单失败, 正在为你重试提交") Log.v("重试已经超过设定次数, 提交失败, 重新查询余票") return False
def rk_create(self, im_string, timeout=60): """ im: 图片字节 im_type: 题目类型 """ params = { 'typeid': 6113, 'timeout': timeout, } params.update(self.base_params) files = {'image': ('a.jpg', im_string)} r = requests.post('http://api.ruokuai.com/create.json', data=params, files=files, headers=self.headers) # Log.v("使用若快进行验证码识别") data = r.json() Log.d(data) return data
def _query_order_wait_time(self): params = { 'random': '%10d' % (time.time() * 1000), 'tourFlag': self.ticket_passenger_info['tour_flag'] or 'dc', '_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token } Log.v("获取订单排队信息...") json_response = send_requests(LOGIN_SESSION, self.URLS['queryOrderWaitTime'], params=params) status, msg = submit_response_checker(json_response, ["status"], True, "排队请求成功") if status: self.wait_time = json_response['data']['waitTime'] self.order_id = json_response['data']['orderId'] people_count = json_response["data"]["waitCount"] msg += " 排队等待时间预计还剩 {0} ms, 排队人数还剩 {1} 人".format( self.wait_time, people_count) if not self.order_id: msg += "\t 订单暂未生成" if "msg" in json_response["data"]: msg += "\t {0}".format(json_response["data"]["msg"]) return status, msg
def _wait_for_order_id(self): # 排队逻辑 t = datetime.datetime.now() # 排队10分钟 delta = datetime.timedelta(minutes=10) while not self.order_id: loop_time = datetime.datetime.now() status, msg = self._query_order_wait_time() Log.v(msg) s, data = find_by_phrase(msg) if s: self.break_submit, self.break_msg = False, data["msg"] return self.break_submit, self.break_msg # 5s 获取排队信息 time.sleep(5) if self.order_id: return True, "OK" if loop_time > t + delta: BlackTrains.add_train(self.train) return False, "提交超时" return False, "排队失败"
def query(self): # 乘客信息最多十五个 retry = 3 while retry: json_response = send_requests(LOGIN_SESSION, PASSENGER_URL_MAPPING, data={"pageIndex": 1, "pageSize": 10}) status, msg = submit_response_checker(json_response, ["status", "data.flag"], True) if not status: self.passengers = [] retry -= 1 Log.v("获取乘客信息失败, 重试中") continue else: self.passengers.extend(json_response["data"]["datas"]) p2_json_response = send_requests(LOGIN_SESSION, PASSENGER_URL_MAPPING, data={"pageIndex": 2, "pageSize": 10}) status, msg = submit_response_checker(p2_json_response, ["status", "data.flag"], True) if not status: self.passengers = [] retry -= 1 Log.v("获取乘客信息失败, 重试中") continue else: self.passengers.extend(p2_json_response["data"]["datas"]) break if not self.passengers: return False Log.v("获取乘客信息成功") return True
def _confirm_single_or_go_for_queue(self): form_data = { 'passengerTicketStr': build_passenger_ticket_string(self.seat_type, self.passenger_data), 'oldPassengerStr': build_oldpassenger_ticket_string(self.passenger_data), 'randCode': '', 'purpose_codes': self.ticket_passenger_info['purpose_codes'], 'key_check_isChange': self.ticket_passenger_info['key_check_isChange'], 'leftTicketStr': self.ticket_passenger_info['leftTicketStr'], 'train_location': self.ticket_passenger_info['train_location'], 'choose_seats': '', # 暂时未加选座 'seatDetailType': '000', 'whatsSelect': '1', 'roomType': '00', 'dwAll': 'N', '_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token, } Log.v("正在为你请求排队提交订单") json_response = send_requests(LOGIN_SESSION, self.URLS['confirmForQueue'], data=form_data) status, msg = submit_response_checker(json_response, ["status", "data.submitStatus"], True, "请求排队成功") return status, msg
def submit_response_checker(response, ok_columns, ok_code, msg="OK"): back_response = copy.copy(response) if not isinstance(response, (list, dict)): return False, '数据非json数据' messages = back_response.get("messages", "") if messages and isinstance("messages", list): Log.v("\n".join(messages)) if messages and isinstance("messages", str): Log.v(messages) for v in ok_columns: response = back_response nest = v.split('.') for v1 in nest: r = response.get(v1, None) if not r: return False, "字段不存在检查失败" else: response = r if response != ok_code: return False, "字段状态不存在" del back_response return True, msg
def _get_passenger_data(self): Log.v("获取乘客信息中..") if PassengerData.passenger: self.passenger_data = PassengerData.find_people_by_names( Config.basic_config.ticket_people_list) # get token from html file. while True: if self.token and self.ticket_passenger_info: break else: self._get_submit_token() msg = "使用缓存的乘客信息导入成功" Log.v(msg) return True, msg # 获取乘客信息并保存 while not self.passenger_data: form_data = {'_json_att': '', 'REPEAT_SUBMIT_TOKEN': self.token} json_response = send_requests(LOGIN_SESSION, self.URLS['getPassengerDTOs'], data=form_data) status, msg = submit_response_checker(json_response, ["status"], True, "获取乘客信息成功") if status: # write data to passenger data. PassengerData.raw_data = json_response['data'][ 'normal_passengers'] PassengerData.get_final_data() self.passenger_data = PassengerData.find_people_by_names( Config.basic_config.ticket_people_list) while True: if self.token and self.ticket_passenger_info: break else: self._get_submit_token() return True, "获取乘客信息, Token信息成功" else: return False, "获取乘客信息失败"
def login(self): count = 0 while self.retry_login_time > count: l = NormalLogin() Log.v("正在为您登录") status, msg = l.login() if not status: count += 1 Log.v("登录失败, 重试{0}次".format(count)) continue else: Log.v("登录成功") break if not self.retry_login_time <= count: Log.v("重试次数已经超过设置") return False return True
def check(self, results): params_data = {'answer': results, 'rand': 'sjrand', 'login_site': 'E'} while True: try: json_response = send_captcha_requests( LOGIN_SESSION, LOGIN_URL_MAPPING["normal"]["captchaCheck"], params=params_data) break except (ResponseCodeError, ResponseError): Log.v("提交验证码错误, 重新提交验证码验证") continue Log.v('验证码校验结果: %s' % json_response) status, msg = json_status(json_response, [], ok_code=self.success_code) if not status: Log.v("验证码识别失败") return status, msg