def send_email(self, msg_type, **extra_var): """ 邮件通知 :param self: :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 = 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) 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 heart_beat_mode(self): if Config.auto_code_enable: status, msg = self.online_checker() Log.v(msg) if not status: Log.e("心跳登录失败,继续重试中,建议手动检查原因再尝试重启") self.online_checker_now()
def run(self): if not self.login(): return p_status = self.query_passengers() if not p_status: return if not Config.auto_code_enable: Log.v("未开启自动打码功能, 不检测用户登录状态") Log.v("正在查询车次余票信息") count = 0 while True: if self.check_maintain(): Log.v("12306系统每天 23:00 - 6:00 之间 维护中, 程序暂时停止运行") maintain_time = self.delta_maintain_time() Log.v("{0}小时 {1}分钟 {2}秒之后重新启动".format( maintain_time.seconds // 3600, (maintain_time.seconds // 60) % 60, maintain_time.seconds % 3600 % 60)) time.sleep(self.delta_maintain_time().total_seconds()) if Config.auto_code_enable: status, msg = self.online_checker() Log.v(msg) if not status: Log.e("心跳登录失败,继续重试中,建议手动检查原因再尝试重启") self.online_checker_now() dates = DispatcherTool.query_travel_dates for query_date in dates: Log.v("查询第 {0} 次".format(count)) n = datetime.datetime.now() data = DispatcherTool.run(query_date) count += 1 self.submit_order(data) DispatcherTool.output_delta_time(n) if self.order_id or self.unfinished_order: break if self.order_id or self.unfinished_order: break if self.order_id: Log.v( "抢票成功,{notice}".format(notice="你已开启邮箱配置,稍后会收到邮件通知" if Config. email_notice_enable else "如需邮件通知请先配置")) Log.v("车票信息:") for order_ticket in self.order_tickets: print(order_ticket) # 抢票成功发邮件信息 send_email( 2, **{ "order_no": self.order_id, "ticket_info": "</br>".join([v.to_html() for v in self.order_tickets]) }) else: Log.v("您有未完成订单, 请及时处理后再运行程序") send_email(3)
def generator_image(self): while True: data = self.getcaptcha() try: img = Image.open(BytesIO(data)) img.close() break except OSError: Log.e("获取验证码图片失败, 重试获取") continue return data
def send_weixin(self, msg_type, **extra_var): if not Config.weixin_notice_enable: Log.v("未开启微信通知") return url = "https://sc.ftqq.com/{key}.send".format(key=Config.weixin_sckey) data = MESSAGES[msg_type] subject = data["subject"] s = data["content"].format(**extra_var) r = requests.post(url, data={"text": subject, "desp": s}) if r.status_code == requests.codes.ok: Log.v("微信通知发送成功") else: Log.e("微信通知发送失败")
def verifyhandle_ruokuai(self): c = RClient() data = c.rk_create(self.generator_image()) if "Result" in data: trans = self.trans_captcha_results(','.join( [str(int(v) - 1) for v in data["Result"]])) self.results = trans return self.check(trans) else: if "Error" in data and data["Error"]: Log.e( "打码平台错误: {0}, 请登录打码平台查看-http://www.ruokuai.com/client/index?6726" .format(data["Error"])) return False, "若快打码平台错误"
def filter_by_config(self): status = self.query() if not status: Log.e("未能获取乘客信息, 请重试") PassengerData.raw_data = self.passengers PassengerData.get_final_data() data = PassengerData.find_people_by_names(Config.basic_config.ticket_people_list) if len(data) == 0: Log.e("乘客信息未在账号中找到, 请检查") return False if len(data) != len(Config.basic_config.ticket_people_list): Log.w("乘客信息配置中包含错误, 已经滤除错误乘客") self.config_passengers = data return True
def send_requests(session, urlmapping_obj, params=None, data=None, **kwargs): session.headers.update(urlmapping_obj.headers) if urlmapping_obj.method.lower() == 'post': session.headers.update( {"Content-Type": r'application/x-www-form-urlencoded; charset=UTF-8'} ) else: session.headers.pop("Content-Type", None) try: Log.d("请求 url {url}".format(url=urlmapping_obj.url)) try: response = session.request(method=urlmapping_obj.method, url=urlmapping_obj.url, params=params, data=data, timeout=10, # allow_redirects=False, **kwargs) except requests.RequestException as e: Log.w(e) Log.w("请求{0}异常 ".format(urlmapping_obj.url)) raise ResponseError if params: Log.d("{url} Get 参数 {data}".format(url=urlmapping_obj.url, data=params)) if data: Log.d("{url} Post 参数 {data}".format(url=urlmapping_obj.url, data=data)) Log.d("返回response url {url}".format(url=response.url)) if response.status_code == requests.codes.ok: if 'xhtml+xml' in response.headers['Content-Type']: data = response.text root = ET.fromstring(data) result = {v.tag: v.text for v in root.getchildren()} return result if 'json' in response.headers['Content-Type']: result = response.json() Log.d("{url} 返回值 {result}".format(url=urlmapping_obj.url, result=result)) return result # other type return response.text else: Log.w(response.url) Log.w(response.status_code) Log.w("返回状态码有问题") except Exception as e: Log.e(e) return None
def login(self): count = 0 while self.retry_login_time >= count: login_instance = NormalLogin() Log.v("正在为您登录") status, msg = login_instance.login() if not status: count += 1 Log.e(msg) Log.v("登录失败, 重试{0}次".format(count)) if self.retry_login_time >= count else "" continue else: Log.v("登录成功") break if self.retry_login_time < count: Log.v("重试次数已经超过设置") return False return True
def send_requests(session, urlmapping_obj, params=None, data=None, **kwargs): session.headers.update(urlmapping_obj.headers) if urlmapping_obj.method.lower() == 'post': session.headers.update({ "Content-Type": r'application/x-www-form-urlencoded; charset=UTF-8' }) else: session.headers.pop("Content-Type", None) if urlmapping_obj.type.lower( ) == 'cdn' and CdnStorage.status and CdnStorage.result: # use cdn to check ticket cdn_ip = CdnStorage.choose_one().ip urlmapping_obj.url = urlmapping_obj.url.replace( parse_url(urlmapping_obj.url).host, cdn_ip) Log.v("当前正在使用CDN IP 为{0}".format(cdn_ip)) try: Log.d("请求 url {url}".format(url=urlmapping_obj.url)) try: if urlmapping_obj.type.lower() == 'cdn': # only query data disable warning urllib3.disable_warnings( urllib3.exceptions.InsecureRequestWarning) response = session.request( method=urlmapping_obj.method, url=urlmapping_obj.url, params=params, data=data, timeout=10, # allow_redirects=False, verify=False, **kwargs) else: response = session.request(method=urlmapping_obj.method, url=urlmapping_obj.url, params=params, data=data, timeout=10, **kwargs) except requests.RequestException as e: Log.w(e) Log.w("请求{0}异常 ".format(urlmapping_obj.url)) raise ResponseError if params: Log.d("{url} Get 参数 {data}".format(url=urlmapping_obj.url, data=params)) if data: Log.d("{url} Post 参数 {data}".format(url=urlmapping_obj.url, data=data)) Log.d("返回response url {url}".format(url=response.url)) if response.status_code == requests.codes.ok: if 'xhtml+xml' in response.headers['Content-Type']: data = response.text root = ET.fromstring(data) result = {v.tag: v.text for v in root.getchildren()} return result if 'json' in response.headers['Content-Type']: result = response.json() Log.d("{url} 返回值 {result}".format(url=urlmapping_obj.url, result=result)) return result # other type return response.text else: Log.w(response.url) Log.w(response.status_code) Log.w("返回状态码有问题") except Exception as e: Log.e(e) return None