def get_materials(m_type: str = 'image', offset: int = 0, count: int = 20) -> dict: """ 获取永久素材的列表,也包含公众号在公众平台官网素材管理模块中新建的图文消息、语音、视频等素材 :param m_type: 素材类型 图片(image)、视频(video)、语音 (voice)、图文(news) :param offset: 从全部素材的该偏移位置开始返回,0表示从第一个素材 返回 :param count: 返回素材的数量,取值在1到20之间 获取素材列表 :return: """ tk = AccessToken.get_token() u = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={}".format( tk) args = {"type": m_type, "offset": offset, "count": count} r = requests.post(u, data=json.dumps(args)) status = r.status_code if status != 200: ms = "获取模板信息时,服务器返回了错误的状态码:{}, time:{}".format(status, datetime.datetime.now()) send_mail(title=ms) raise ValueError(ms) else: data = r.json() return data
def backup_reg(*args, **kwargs): """备份注册""" res = backup() title = res['title'] content = "{}".format(res['content']) send_mail(title=title, content=content) return "backup_reg success"
def generator_yesterday_health_report(*args, **kwargs): """ 生成昨天的健康报告 此任务应该被定时装置调用,在每天的凌晨2点-3点运行. :param args: :param kwargs: :return: """ now = datetime.datetime.now() yesterday = now - datetime.timedelta(days=1) title = "{}健康报告生成日志".format(now.strftime("%F")) content = '' user_ids = User.get_all_user_id() for user_id in user_ids: try: res = HealthReport.get_instance(user_id, yesterday) if res is None: ms = "{},用户 {} 生成安全报告失败".format( now.strftime("%Y-%m-%d %H:%M:%S"), user_id) content += "{}\n".format(ms) logger.exception(ms) except Exception as e: ms = "{},用户 {} 生成安全报告出错,错误原因:{}".format( now.strftime("%Y-%m-%d %H:%M:%S"), user_id, str(e)) content += "{}\n".format(ms) print(e) logger.exception(ms) finally: pass if content != "": """有内容的时候才发送邮件""" send_mail(title=title, content=content)
def login_func(): """ 接收登录信息函数 :return: """ mes = {"message": "success"} form = FlaskForm() if form.validate_on_submit(): args = get_args(request) args.pop('csrf_token', None) try: mes = UserInfo.login(**args) except Exception as e: n = datetime.datetime.now() t = "官网登录失败.{}".format(n) c = "args:{}, auth:{}, error:{}".format(args, AUTH, e) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) finally: if mes['message'] == "success": """登录成功""" session['_id'] = mes.pop('_id') # 保存会话 else: pass else: mes['message'] = "提交错误,请刷新页面后重试" return json.dumps(mes)
def reboot_plan(current: datetime.datetime = None) -> None: """ 检查系统是否需要重启系统. 行为: 1. 计划重启, 内存占用率利用率超过75%后,将在临陈4:30重启 2. 紧急重启. 内存占用率超95%时,立即重启. 重启之前都会清除日志文件. :param current: :return: """ per = memory_percent() current = datetime.datetime.now() if not isinstance(current, datetime.datetime) else current h = current.hour m = current.minute if per >= 95: """清除日志,立即重启""" clear_log() title = "立即重启金10数据系统:{}".format(current) content = "当前内存使用率: {}".format(per) send_mail(title=title, content=content) os.system("reboot") else: if h == 4 and abs(m - 20) < 10 and per >= 50: """凌晨4:30分左右""" clear_log() title = "维护重启金10数据系统:{}".format(current) content = "当前内存使用率: {}".format(per) send_mail(title=title, content=content) os.system("reboot") else: pass
def backup_reg_today(*args, **kwargs): """备份今日注册""" res = backup(show_today=True) title = res['title'] content = "{}".format(res['content']) # send_mail(to_email='*****@*****.**', title=title, content=content) send_mail(title=title, content=content) return "backup_reg_today success"
def parse_page(domain: str = None, t_type: str = None, ticket_limit: int = None) -> list: """ 分析某一类型的页面数据,并返回结果的list,此函数必须按照交易类型分别调用 :param domain: 平台域名 :param t_type: 交易类型,None表示是出金申请 :param ticket_limit: ticket下限,不能小于此值 :return: """ res = list() stop = False s = requests.Session() if open_platform(s, domain): for i in range(15, 9999999999): if t_type is None: """出金申请""" url = withdraw_url_base2.format(i) html = get_page_platform(s, url) records = extract_withdraw_table(html) if isinstance(records, list) and len(records) > 0: temp = extend_data(res, records, ticket_limit) res = temp['data'] stop = temp['stop'] else: print("stop page by empty: {}".format(url)) break else: url = get_page_url(domain, t_type, i) html = get_page_platform(s, url) records = extract_transaction_table(html, domain) count = 0 while len(records) == 0 and count < 3: time.sleep(3) html = get_page_platform(s, url) records = extract_transaction_table(html, domain) count += 1 if isinstance(records, list) and len(records) > 0: temp = extend_data(res, records, ticket_limit) res = temp['data'] stop = temp['stop'] else: print("stop page by empty: {}".format(url)) break if stop: print("stop page by flag: {}".format(url)) break else: pass else: title = "{}打开平台失败".format(domain) content = "{} 平台: {} ".format(datetime.datetime.now(), domain) send_mail(title=title, content=content) logger.exception(msg=title) raise ValueError(title) return res
def calculate_score_and_send_mail(): """ 每周一计算微信用户的积分并发送邮件. :return: """ l = Score.every_week_mon_check() now = datetime.datetime.now() title = "{}, 扣分报告".format(now) content = "{}".format(l) send_mail(title=title, content=content)
def check_server_and_send_mail(): """ 检查副本集合的服务器是否在线?如果不在线的话就发送email.(只有在状态改变的时候才发生送email) :param args: :param kwargs: :return: """ """ status_dict是存放上一次服务器探测结果的字典,以服务器的 ip+":"+port为key,相关信息字典为value { "192.168.0.110:27017": {"ip":"192.168.0.110","port":"27017", "last_time":"2017-11-27 10:11:21.940", "last_status": True}, .... } """ global replica_hosts for host in replica_hosts: ip = host['host'] port = host['port'] fail_count = host['fail_count'] status = host['status'] mes = '' try: t = telnetlib.Telnet(host=ip, port=port, timeout=5) t.close() except Exception as e: mes = "{}:{}连接失败,错误原因:{}".format(ip, port, e) logger.exception(mes) print(e) finally: now = datetime.datetime.now() if mes != '': """连接发生异常""" now_status = "off_line" fail_count.append(now) if len(fail_count) >= 2: """连续失败2次以上""" fail_count = fail_count[-2:] else: pass else: now_status = "on_line" fail_count.clear() if status != now_status: status = now_status title = "来自scanner的检测: {}服务器检测{}".format( ip, "正常" if status == "on_line" else "失败") content = "来自 39.108.67.178的探测结果 {} 服务器{}:{},mongodb例行检查结果:{}".format( now, ip, port, status) send_mail(title=title, content=content) host['fail_count'] = fail_count host['status'] = status else: pass
def query_city_by_plate_number(cls, plate_number: str) -> (dict, None): """ 根据车牌,从聚合数据查询归属地的信息. :param plate_number: :return: 例子: { "reason":"查询成功", "result":{ "city_name":"宜春", "city_code":"JX_YICHUN_J", "abbr":"赣C", "engine":"1", "engineno":"6", "classa":"1", "classno":"6", "province":"江西" }, "error_code":0 } """ p = plate_number[0: 2] p = quote(p, encoding="utf-8") is_new = 0 if len(plate_number) == 7 else 1 # 是否能能源车? u = "http://v.juhe.cn/sweizhang/carPre?hphm={}&isNer={}&key={}".format(p, is_new, app_key) r = requests.get(url=u) status_code = r.status_code if status_code != 200: ms = "查询聚合数据的违章查询直连接口的车牌和城市的对应关系时出错,服务器返回了错误代码:{}".format(status_code) logger.exception(ms) print(ms) title = "{}聚合数据接口出错".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) send_mail(title=title, content=ms) raise ValueError(ms) else: r = r.json() if r['reason'] == "查询成功": temp = r['result'] res = dict() res['city_code'] = temp['city_code'] res['city_name'] = temp['city_name'] res['need_vin'] = bool(int(temp['classa'])) res['need_engine'] = bool(int(temp['engine'])) res['vin_length'] = int(temp['classno']) res['engine_length'] = int(temp['engineno']) res['new_power'] = bool(is_new) return res else: ms = "询直连接口的车牌和城市的对应关系时返回了出错信息:{}".format(r) logger.exception(ms) raise ValueError(ms)
def sms_func(action): """短信视图""" mes = {"message": "success"} if action in ['get', 'send']: """发送短信""" form = FlaskForm() if form.validate_on_submit(): phone = get_arg(request, "phone", "") if check_phone(phone): """手机号码合法""" u = "http://file.bhxxjs.cn/api/get_sms" args = {"phone": phone} r = None try: r = requests.post(u, params=args, headers=hs, timeout=3) except Exception as e: n = datetime.datetime.now() t = "调用短信接口失败.{}".format(n) c = "args:{}, auth:{}, error:{}".format(args, AUTH, e) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) finally: if r is None: mes['message'] = "短信服务暂时不可用" else: status = r.status_code if status != 200: mes['message'] = "短信服务未工作" n = datetime.datetime.now() t = "调用短信接口返回了错误的状态.{}".format(n) c = "args:{}, auth:{}, status:{}".format( args, AUTH, status) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) else: mes = r.json() title = "新用户注册 {}".format(datetime.datetime.now()) content = "手机号码: {}".format(phone) send_mail2(title=title, content=content) else: """手机号码非法""" mes['message'] = '手机号码非法' else: mes['message'] = "提交错误,请刷新页面后重试" else: mes['message'] = '未知的操作' return json.dumps(mes)
def last_record(cls) -> dict: """ 获取数据库最新的一条记录 :return: """ resp = None s = [("time", -1)] try: resp = cls.find_one(sort=s) except Exception as e: print(e) title = "读取最后一条金10数据出错: {}".format(datetime.datetime.now()) send_mail(title=title) finally: return dict() if resp is None else resp
def to_jiandao_cloud_and_send_mail(*args, **kwargs): """ 使用handless浏览器向简道云写入注册信息,2018-10-21后,此方法不再使用.转而使用api的方式. :param args: :param kwargs: :return: """ print(kwargs) res = to_jiandao_cloud(**kwargs) if not res: title = "{} 发送数据到简道云失败".format( datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) content = str(kwargs) send_mail("*****@*****.**", title, content) return res
def get_templates() -> list: """ 获取全部的模板信息 :return: """ u = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token={}".\ format(AccessToken.get_token()) r = requests.get(u) status = r.status_code if status != 200: ms = "获取模板信息时,服务器返回了错误的状态码:{}, time:{}".format(status, datetime.datetime.now()) send_mail(title=ms) raise ValueError(ms) else: data = r.json() data
def send_signal(send_data: dict, token_name: str = None) -> bool: """ 发送信号 :param send_data:发动的信息字典 :param token_name: token映射的key,对应url_map的key :return: """ res = False token = url_map.get(token_name) if token is None: ms = "不存在的token_name:{}".format(token_name) now = datetime.datetime.now() title = "{}{}".format(ms, now) send_mail(title=title) logger.exception(ms) raise ValueError(ms) else: data = json.dumps(send_data) headers = {'Content-Type': 'application/json'} base_url = "https://oapi.dingtalk.com/robot/send?access_token=" robot_url = "{}{}".format(base_url, token) now = datetime.datetime.now() r = None try: r = requests.post(robot_url, data=data, headers=headers) except Exception as e: title = "调用钉钉机器人接口异常!{}".format(now) content = "{}, 错误原因: {}".format(title, str(e)) send_mail(title=title, content=content) logger.exception(e) print(e) finally: if r is not None: status_code = r.status_code else: status_code = -1 if status_code == 200: r = r.json() if r['errmsg'] == 'ok': """success""" res = True else: ms = '发送消息到钉钉机器人失败,错误原因:{}, 参数{}'.format(r['errmsg'], data) title = "发送消息到钉钉机器人失败{}".format(ms, now) send_mail(title=title, content=ms) logger.exception(ms) raise ValueError(ms) else: ms = '钉钉机器人没有返回正确的响应,错误代码:{}'.format(status_code) now = datetime.datetime.now() send_mail(title="{}{}".format(now, ms)) logger.exception(ms) raise ValueError(ms) return res
def send_reg_info_celery2(self, send_data: dict): """ 发送注册信息到简道云 2018-11-12 此函数不再使用. 发送消息到简道云使用同步api方式 :param self: :param send_data: :return: """ resp = RegisterLog.send_reg_info(**send_data) if resp['message'] != "success": try: self.retry(countdown=5, max_retries=3) except exceptions.MaxRetriesExceededError as e: ms = "celery钉钉消息失败,已达最重试次数,{}".format(send_data) title = "celery钉钉消息失败.{}".format(datetime.datetime.now()) c = "{} , 执行结果:{}. 重试失败原因:{}".format(ms, resp, e) print(ms) print(e) send_mail(title=title, content=c) print(resp)
def get_ticket(cls) -> (str, None): """ 从本机获取一个jsapi_ticket. 并注意过期时间. 这是应用程序获取jsapi_ticket的主要方法. :return: """ res = None f = dict() s = {"time": -1} one = cls.find_one_plus(filter_dict=f, sort_dict=s, instance=False) flag = False if one is None: flag = True else: """检查access_token是否过期""" generate_time = one['time'] expires = one['expires'] token = one['ticket'] now = datetime.datetime.now() delta = (now - generate_time).total_seconds() timeout = expires - delta if timeout <= 0: """超期了""" flag = True elif 0 <= timeout <= 300: """可以开始申请了""" flag = True res = token else: res = token if flag: """从互联网查询""" resp = cls.get_ticket_from_api() mes = resp['message'] if mes != "success": """从互联网查询失败""" title = "查询access_token失败,错误原因:{}, {}".format( mes, datetime.datetime.now()) send_mail(title=title) else: data = resp['data'] res = data['ticket'] return res
def logger_request_info(): """ 监控所有的请求信息 :return: """ data = None try: data = RawRequestInfo.get_init_dict(req=request) mes = RawRequestInfo(**data) mes.set_attr("server", "quotations_server") mes.save_plus() except Exception as e: ms = "Error: {}, data: {}".format(e, data) logger.exception(msg=ms) send_mail(title="{}Message_Server监听请求出错".format( datetime.datetime.now()), content=ms) finally: if request.url.startswith("http://www.baidu.com"): return abort(404)
def get_browser(headless: bool = True) -> Firefox: """ 获取一个浏览器 :param headless: :return: """ profile = FirefoxProfile() """ 因为headless的浏览器的语言跟随操作系统,为了保证爬回来的数据是正确的语言, 这里必须设置浏览器的初始化参数, 注意,使用headless必须先安装对应浏览器正常的版本,然后再安装headless版本 比如火狐的headless 下载火狐的geckodriver驱动。(当前文件夹下已经有一个了)地址是: https://github.com/mozilla/geckodriver/releases 下载后解压是一个geckodriver 文件。拷贝到/usr/local/bin目录下,然后加上可执行的权限 sudo chmod +x /usr/local/bin/geckodriver """ profile.set_preference("intl.accept_languages", "zh-cn") options = FirefoxOptions() options.add_argument("--headless") if headless: try: browser = Firefox(firefox_profile=profile, firefox_options=options) except Exception as e: title = "JDY {} headless浏览器打开失败".format(datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) recode(e) logger.exception(e) raise e else: try: browser = Firefox(firefox_profile=profile) except Exception as e: title = "JDY {} headless浏览器打开失败".format(datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) recode(e) logger.exception(e) raise e return browser
def regular() -> None: """ 定期执行爬虫任务 :return: """ u = "http://127.0.0.1:7999/news" browser = get_browser(headless=True, browser_class=1) open_url(url=u, browser=browser) prev_refresh = datetime.datetime.now() title = "金10数据系统已启动:{}".format(prev_refresh) send_mail(title=title) while 1: now = datetime.datetime.now() if (now - prev_refresh).total_seconds() > 3600: """1小时刷新一次页面""" browser.delete_all_cookies() # 清理缓存 browser.refresh() # 刷新页面 else: pass calendar_data, last_date = get_calendar_data(browser) news_data = get_news_data(b=browser) if len(news_data) == 0 and len(calendar_data) == 0: pass else: data = { "strategy": [], "news": news_data, "calendar": calendar_data } save_data(data=data, last_date=last_date) end = datetime.datetime.now() print(now) print(end) delay = 8 - (end - now).total_seconds() print("delay is {}".format(delay)) delay = 1 if delay < 0 else delay prev_refresh = end """检查是否需要重启""" reboot_plan(current=now) time.sleep(delay)
def refresh(cls): """ 从聚合数据提供的接口,刷新可用城市列表 :return: """ u = "http://v.juhe.cn/sweizhang/citys?province=&dtype=&key={}".format(app_key) r = requests.get(url=u) status_code = r.status_code if status_code != 200: ms = "查询聚合数据的违章查询直连接口的支持城市时出错,服务器返回了错误代码:{}".format(status_code) logger.exception(ms) print(ms) title = "{}聚合数据接口出错".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) send_mail(title=title, content=ms) else: raw = r.json()['result'] instances = cls.batch_create(raw) old_list = cls.find_plus(filter_dict=dict(), to_dict=True, can_json=False) old_dict = {x['city_code']: x for x in old_list} old_keys = old_dict.keys() for instance in instances: city_code = instance['city_code'] if city_code in old_keys: """数据库已存在的城市记录,需要比对""" temp = old_dict[city_code] instance['_id'] = temp['_id'] instance['first_letter'] = temp['first_letter'] old_dict.pop(city_code, None) else: pass obj = cls(**instance) obj.save_plus(upsert=True) ids = list(old_dict.keys()) if len(ids) == 0: pass else: f = {"city_code": {"$in": ids}} u = {"$set": {"can_use": False}} cls.update_many_plus(filter_dict=f, update_dict=u, upsert=True)
def send_last_pio_celery(position): """ 发送用户最后的位置信息到socketio服务器,调用本函数的目前只有api.data.data_view.gps_push函数. 此函数是同步模式的接收app发送的gps信息.确保调用本函数的地方尽可能的少以保证逻辑的简单性. 对于压缩包的gps信息,由于是历史信息,所以没必要发送.而且压缩包一旦可以发送的时候,gps实时数据也必然 恢复了,肯定比压缩包的gps信息更新,所以对压缩包的gps信息处理时,没必要调用本函数. : param position: 一个可以被json序列化的dict : return: None """ mes = {"the_type": "last_position", "data": json.dumps(position)} status = 200 error = None try: r = requests.post("http://127.0.0.1:5006/listen", data=mes) status = r.status_code except Exception as e: status = -1 error = e finally: global prev_resp_status if status != prev_resp_status: """可以发送邮件""" if status == 200: ms = "保驾犬平台send_last_pio_celery函数发送位置信息恢复正常." else: ms = "保驾犬平台send_last_pio_celery函数发送位置信息失败," now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") if error is None: content = "{}.{},服务器返回状态码:{}".format(now, ms, status) else: content = "{}.{},服务器返回状态码:{},错误原因:{}".format( now, ms, status, error.__str__()) prev_resp_status = status send_mail(title=ms, content=content) else: pass return status
def listen(cls, info: dict) -> bytes: """ 监听微信推送的事件消息(比如关注公众号, 扫码等). 检查info字典中的消息类型,如果有对应的处理函数就进行相应的处理 下面是一些xml信息的示范 1. 取消关注 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603763", "MsgType" : "event", "Event" : "unsubscribe", "EventKey" : null, "create_time" : ISODate("2018-08-30T12:36:03.000Z") } 2. 关注公众号 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603863", "MsgType" : "event", "Event" : "subscribe", "EventKey" : null, "create_time" : ISODate("2018-08-30T12:37:43.000Z") } 3. 扫描委托求职二维码 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603967", "MsgType" : "event", "Event" : "SCAN", "EventKey" : "relate_5b56c0f87b3128ec21daa693", "Ticket" : "gQEd8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyZWhPaDBTNG5jaGwxMDAwMGcwN2IAAgRq22tbAwQAAAAA", "create_time" : ISODate("2018-08-30T12:39:27.000Z") } 4. 用户公众号发文本消息 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535604037", "MsgType" : "text", "Content" : "你好", "MsgId" : "6595369118955706758", "create_time" : ISODate("2018-08-30T12:40:37.000Z") } 5. 用户公众号发图片 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535604081", "MsgType" : "image", "PicUrl" : "http://mmbiz.qpic.cn/mmbiz_jpg/tsJ9TEnc4GLT0fthC4Irho1XpSQiaiauVKLvS3V5tmdiaQJGmibYUFN8UMiaJF6m7r7MFYqHUK8iaqBynUL2TuvAaicLg/0", "MsgId" : "6595369307934267784", "MediaId" : "rcnvWQheiwfu3de7ThXV7ksvV_KK5FGKuiO1kNJ1_c4Zh3vQ59Qc4ottyvH1ozYM", "create_time" : ISODate("2018-08-30T12:41:21.000Z") } :param info: 消息字典,就是WebChatMessage的实例的doc :return: """ res = b'' if "xml" in info: now = datetime.datetime.now() xml = info['xml'] msg_type = xml['MsgType'].lower() openid = xml['FromUserName'] if msg_type == "event": """事件""" event = xml['Event'].lower() if event == "subscribe": """关注公众号""" f = {"openid": openid} u = {"$set": {"subscribe": 1}} WXUser.find_one_and_update(filter_dict=f, update_dict=u, upsert=True) # 文本不能换行 data = "你好,欢迎关注汇赢智能! \n 独立创新的智能交易平台,为用户提供全球先进的跟随交易系统以及优质的信号源;完善风控体系,让科技颠覆收益,让智能负责收益!" data = "你好,欢迎关注汇赢智能! \n 独立创新的智能交易平台,为用户提供全球先进的跟随交易系统以及优质的信号源;完善风控体系,让科技颠覆收益,让智能负责收益!" res = XMLMessage.produce(to_user=openid, msg_type="text", data=data) elif event == "unsubscribe": """取消关注""" ms = "用户: {} 取消关注".format(openid) logger.info(ms) print(ms) f = {"openid": openid} u = {"$set": {"subscribe": 0}} WXUser.find_one_and_update(filter_dict=f, update_dict=u, upsert=False) elif event == "scan": """扫码""" event_key = xml['EventKey'] # 场景id print("event_key is {}".format(event_key)) if event_key == "456": """扫码关注公众号""" ms = "{}扫码关注公众号".format(openid) logger.info(msg=ms) else: title = "{} 未意料的扫码事件消息:{}.{}".format( now, msg_type, event_key) content = "{}".format(str(info)) send_mail(title=title, content=content) elif event == "view": """点击菜单""" elif event == "templatesendjobfinish": """模板消息发送结果""" pass else: title = "{} 未意料的事件消息:{}.{}".format(now, msg_type, event) content = "{}".format(str(info)) send_mail(title=title, content=content) elif msg_type == "text": """文本消息""" s = xml['Content'] if s == "喊单": """回复老师喊单登录的链接""" data = "芝麻开门. <a href='http://wx.yataitouzigl.com/teacher/login.html'>分析师登录入口</a>" res = XMLMessage.produce(to_user=openid, msg_type="text", data=data) else: pass elif msg_type == "image": """图片消息""" else: title = "{} 未意料的类型:{}".format(now, msg_type) content = "{}".format(str(info)) send_mail(title=title, content=content) else: pass return res
def reg_func(): """ 接收注册信息函数 :return: """ mes = {"message": "success"} form = FlaskForm() if form.validate_on_submit(): args = get_args(request) args.pop('csrf_token', None) """检查短信验证码""" phone = args.pop("phone", "") code = args.pop("code", "") password = args.pop("password", "") if phone == '' or password == '' or code == '': mes['message'] = "缺少必要的信息" else: """检查短信验证码""" f = {"phone": phone, 'code': code} u = "http://file.bhxxjs.cn/api/validate_code" # u = "http://127.0.0.1:7001/api/validate_code" r = None try: r = requests.get(u, params=f, headers=hs) except Exception as e: n = datetime.datetime.now() t = "短信验证接口调用失败.{}".format(n) c = "args:{}, auth:{}, error:{}".format(f, AUTH, e) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) finally: status = r.status_code if hasattr(r, 'status_code') else None if status != 200: mes['message'] = "验证短信服务未工作" n = datetime.datetime.now() t = "调用验证短信服务接口返回了错误的状态.{}".format(n) c = "args:{}, auth:{}, status:{}".format( args, AUTH, status) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) else: r = r.json() if r['message'] != "success": mes['message'] = "短信验证失败" else: """验证成功.向后台提交注册信息""" args = {"loginname": phone, "password": password} r = None u = "http://www.bhxxjs.cn:8080/bdurs/user/toAddUser" # u = "http://192.168.1.107:8080/BDUrs/user/toAddUser" try: r = requests.get(u, params=args, headers=hs, timeout=3) except Exception as e: n = datetime.datetime.now() t = "调用注册接口失败.{}".format(n) c = "args:{}, auth:{}, error:{}".format( args, AUTH, e) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) finally: if r is None: mes['message'] = "注册服务暂时不可用" else: status = r.status_code if status != 200: mes['message'] = "注册服务未工作" n = datetime.datetime.now() t = "调用注册服务接口返回了错误的状态.{}".format(n) c = "args:{}, auth:{}, status:{}".format( args, AUTH, status) send_mail(title=t, content=c) ms = "{} {}".format(t, c) logger.exception(msg=ms) else: """保存到mongodb""" args = { "phone": phone, "password": password } mes = UserInfo.register(**args) else: mes['message'] = "提交错误,请刷新页面后重试" return json.dumps(mes)
def listen(cls, info: dict) -> bytes: """ 监听微信推送的事件消息(比如关注公众号, 扫码等). 检查info字典中的消息类型,如果有对应的处理函数就进行相应的处理 下面是一些xml信息的示范 1. 取消关注 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603763", "MsgType" : "event", "Event" : "unsubscribe", "EventKey" : null, "create_time" : ISODate("2018-08-30T12:36:03.000Z") } 2. 关注公众号 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603863", "MsgType" : "event", "Event" : "subscribe", "EventKey" : null, "create_time" : ISODate("2018-08-30T12:37:43.000Z") } 3. 扫描委托求职二维码 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535603967", "MsgType" : "event", "Event" : "SCAN", "EventKey" : "relate_5b56c0f87b3128ec21daa693", "Ticket" : "gQEd8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyZWhPaDBTNG5jaGwxMDAwMGcwN2IAAgRq22tbAwQAAAAA", "create_time" : ISODate("2018-08-30T12:39:27.000Z") } 4. 用户公众号发文本消息 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535604037", "MsgType" : "text", "Content" : "你好", "MsgId" : "6595369118955706758", "create_time" : ISODate("2018-08-30T12:40:37.000Z") } 5. 用户公众号发图片 { "ToUserName" : "gh_134657758ddf", "FromUserName" : "oBBcR1T5r6FCqOo2WNxMqPUqvK_I", "CreateTime" : "1535604081", "MsgType" : "image", "PicUrl" : "http://mmbiz.qpic.cn/mmbiz_jpg/tsJ9TEnc4GLT0fthC4Irho1XpSQiaiauVKLvS3V5tmdiaQJGmibYUFN8UMiaJF6m7r7MFYqHUK8iaqBynUL2TuvAaicLg/0", "MsgId" : "6595369307934267784", "MediaId" : "rcnvWQheiwfu3de7ThXV7ksvV_KK5FGKuiO1kNJ1_c4Zh3vQ59Qc4ottyvH1ozYM", "create_time" : ISODate("2018-08-30T12:41:21.000Z") } :param info: 消息字典,就是WebChatMessage的实例的doc :return: """ res = b'' if "xml" in info: now = datetime.datetime.now() xml = info['xml'] msg_type = xml['MsgType'].lower() openid = xml['FromUserName'] if msg_type == "event": """事件""" event = xml['Event'].lower() if event == "subscribe": """关注公众号""" f = {"openid": openid} u = {"$set": {"subscribe": 1}} WXUser.find_one_and_update_plus(filter_dict=f, update_dict=u, upsert=True) data1 = [ { "title": "卡佑欢迎你", "img_url": "http://mmbiz.qpic.cn/mmbiz_jpg/KCRpHfdSvS4f5tNDutYeOQGm727dzQyWps0zM6WuRHm" "LrvwsxibtvxcZEAtToiaUEibHgRaj28o8PAp7edhUcKMNw/0?wx_fmt=jpeg", "desc": "大企业,工作有保障,专业平台 合法营运 收入稳定 合作共赢 福利保障 五险一金 安全保障 专人服务", "url": "http://temp.safego.org/wx/html/about.html" }, { "title": "找工作,用卡佑!欢迎新老司机加入, 好工作不等人.现在就去填写简历.", "img_url": "http://mmbiz.qpic.cn/mmbiz_jpg/KCRpHfdSvS4f5tNDutYeOQGm727dzQyWS62gcmK44lRRoJ" "dv9SkicUl2HZJKictiaV7tdWCUZYMkDcr9pFJAC02vA/0?wx_fmt=jpeg", "desc": "收入稳定, 福利齐全, 欢迎老司机加入, 点此填写简历", "url": "http://temp.safego.org/wx/html/register.html" } ] data = [{ "title": "卡佑欢迎你", "img_url": "http://mmbiz.qpic.cn/mmbiz_jpg/KCRpHfdSvS4f5tNDutYeOQGm727dzQyWps0zM6WuRHm" "LrvwsxibtvxcZEAtToiaUEibHgRaj28o8PAp7edhUcKMNw/0?wx_fmt=jpeg", "desc": "大企业,工作有保障,专业平台 合法营运 收入稳定 合作共赢 福利保障 五险一金 安全保障 专人服务", "url": "http://temp.safego.org/wx/html/register.html" }] res = XMLMessage.produce(to_user=openid, msg_type="news", data=data1) elif event == "unsubscribe": """取消关注""" ms = "用户: {} 取消关注".format(openid) logger.info(ms) print(ms) f = {"openid": openid} u = {"$set": {"subscribe": 0}} WXUser.find_one_and_update_plus(filter_dict=f, update_dict=u, upsert=False) elif event == "scan": """扫码""" event_key = xml['EventKey'] print("event_key is {}".format(event_key)) if event_key.startswith("relate_"): """扫描委托求职二维码""" f = {"openid": openid} user = WXUser.find_one_plus(filter_dict=f, instance=False) data = '' if user is None: data = "尊敬的用户,请先关注卡佑公众号再进行操作" else: phone = user.get("phone", "") resume_id = user.get("resume_id", "") print("phone is {}".format(phone)) print("resume_id is {}".format(resume_id)) if not isinstance(resume_id, ObjectId): data = "卡佑助手提醒: 你还没填写自己的简历,请点击<a href='http://temp.safego.org/wx/html/register_info." \ "html'>这里填写简历</a>" elif len(phone) != 11: data = "卡佑助手提醒: 你还没绑定手机,请点击<a href='http://temp.safego.org/wx/html/register." \ "html'>这里填写进行绑定</a>" else: s_id = event_key.split("relate_")[-1] sales = WXUser.find_by_id(o_id=s_id, to_dict=True) if sales is None: pass else: s_name = sales['name'] if sales.get("name") else sales.get("nick_name", "") data = "卡佑助手提醒: {}已接受你的求职委托.".format(s_name) if data == "": pass else: res = XMLMessage.produce(to_user=openid, msg_type="text", data=data) elif event_key == "456": """扫码关注公众号""" ms = "{}扫码关注公众号".format(openid) logger.info(msg=ms) else: title = "{} 未意料的扫码事件消息:{}.{}".format(now, msg_type, event_key) content = "{}".format(str(info)) send_mail(title=title, content=content) elif event == "view": """点击菜单""" else: title = "{} 未意料的事件消息:{}.{}".format(now, msg_type, event) content = "{}".format(str(info)) send_mail(title=title, content=content) elif msg_type == "text": """文本消息""" s = xml['Content'] data = "测试文本消息, 你输入的内容是: '{}'".format(s) res = XMLMessage.produce(to_user=openid, msg_type="text", data=data) elif msg_type == "image": """图片消息""" else: title = "{} 未意料的类型:{}".format(now, msg_type) content = "{}".format(str(info)) send_mail(title=title, content=content) else: pass return res
def new_order_message1(t_id: str, t_name: str, product: str, order_type: str, enter_time: str, enter_price: (str, float, int), direction: str, exit_time: str = None, exit_price: (str, float, int) = None) -> bool: """ 新订单模板消息,使用批量发送. 2018-10-25启用,同步函数 待发送的模板消息字典 格式: 2018-10-18之前: {'t_id': '5b8c5452dbea62189b5c28f9', 'order_type': '开仓'} 2018-10-18之后: { 'product': '原油', 'order_type': '开仓', 'enter_time': datetime.datetime(2018, 10, 18, 3, 53, 11, 670692), 'exit_time': datetime.datetime(2018, 10, 18, 3, 53, 11, 670692), # 只有平仓才有 't_id': 5b8c5452dbea62189b5c28f9, 't_name': 非功, 'enter_price': 69.955, 'exit_price': 69.955, # 只有平仓才有 } :param t_id: :param t_name: :param product: :param order_type: :param enter_time: :param enter_price: :param exit_time: :param exit_price: :return: """ ms = "new_order_message1正在处理发送请求:t_name={}, t_id={}".format(t_name, t_id) logger.info(ms) # send_mail(title="func begin...", content='{}'.format(datetime.datetime.now())) ses = mongo_db.get_conn("teacher") t_id = ObjectId(t_id) if isinstance(t_id, str) else t_id f = {"_id": t_id} p = {"_id", "name"} t = ses.find_one(filter=f, projection=p) if t is None: ms = "发送模板消息出错,无效的t_id:{}".format(t_id) logger.exception(msg=ms) send_mail(title=ms) return False else: t_id = t['_id'] t_name = t['name'] f = {"follow": {"$elemMatch": {"$in": [t_id]}}} p = ['_id', "openid", "nick_name"] now = datetime.datetime.now() ses = mongo_db.get_conn(table_name="wx_user") us = ses.find(filter=f, projection=p) us = [x for x in us] us_l = len(us) # send_mail(title="if begin ...", content='us_l={}, {}'.format(us_l, datetime.datetime.now())) ms = "准备发送{}条模板消息,查询条件={}".format(us_l, f) # send_mail(title=ms) logger.info(msg=ms) if us_l > 0: u = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}".format( AccessToken.get_token()) info = {"t_id": t_id, "t_name": t_name, "time": now} doc_list = [] # 发送成功的结果集.需要记录到数据库 with requests.Session() as ses: for x in us: openid = x['openid'] nick_name = x['nick_name'] info['openid'] = openid info['nick_name'] = nick_name # send_mail(title="for begin ...", content='{}'.format(datetime.datetime.now())) template_id = 'bc6Z0AhnPbisIxK6ZuPtuLR9L0aNNu01uNg_fKHfy8I' args = { "touser": openid, "template_id": template_id, "url": "http://wx.91master.cn/user/html/currentCrunchy.html?t_id={}" .format( str(t_id) if isinstance(t_id, ObjectId) else t_id), "data": { "first": { "value": "你关注的{}老师有新的操作.".format(t_name), "color": "grey", }, "keyword1": { "value": "建仓" if order_type == "开仓" else order_type, # 订单类型 "color": "#82B6F4", }, "keyword2": { "value": direction, # 交易方向 "color": "#82B6F4" }, "keyword3": { "value": '', # 交易手数 "color": "#82B6F4" }, "keyword4": { "value": product, # 交易品种 "color": "#82B6F4" }, "keyword5": { "value": enter_price if order_type == "开仓" else exit_price, # 开仓/平仓价格 "color": "#82B6F4" }, "remark": { "value": "此信息代表{}老师个人观点,仅供参考.不作为入市依据.点击“详情”查看完整信息". format(t_name), "color": "#dc1c1c" } } } title = "发送给{}的模板消息".format(nick_name) content = "模板消息内容 data={}".format(args) ms = "{} | {}".format(title, content) logger.info(ms) response = ses.post(url=u, data=json.dumps(args), timeout=5) status = response.status_code if status == 200: resp = response.json() if isinstance(resp, dict): info['return'] = "success" info.update(resp) else: info['return'] = "error" info['_id'] = ObjectId() info['args'] = args info['time'] = now doc_list.append(info) else: title = "调用微信模板消息接口出错,{}".format(now) content = "微信模板接口返回了错误的代码:{}".format(status) send_mail(title=title, content=content) """检查结果集""" if len(doc_list) > 0: col = TemplateMessageResponse.get_collection() col.insert_many(documents=doc_list) else: pass return True else: return False
def query_vio_from_api(plate_number: str, vin: str, engine_id: str, city_code: str, car_type: str) -> dict: """ 从聚合数据的接口查询违章信息. :param plate_number: :param vin: :param engine_id: :param city_code: :param car_type: 车辆类型? 01:大型车,02:小型车, 51:新能源大型车 52:新能源小型车 :return:{'message': '发动机号错误','data';{''violations}: [violation1,....], amount:2,....} """ mes = {"message": "success"} u = "http://v.juhe.cn/sweizhang/query?dtype=&callback=&city={}&hphm={}&hpzl={}&engineno={}&classno={}&key={}".\ format(city_code, quote(plate_number, encoding='utf-8'), car_type, engine_id, vin, app_key) r = requests.get(url=u) status_code = r.status_code if status_code != 200: ms = "查询聚合数据的违章查询直连接口的车牌和城市的对应关系时出错,服务器返回了错误代码:{}".format(status_code) logger.exception(ms) print(ms) title = "{}聚合数据接口出错".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) send_mail(title=title, content=ms) mes['message'] = ms else: r = r.json() """ 查询成功的示范 r = { 'reason': '查询成功', 'resultcode': '200', 'error_code': 0, 'result': { 'lists': [ { 'archiveno': '', 'date': '2018-03-17 15:12:00', 'act': '驾驶中型以上载货汽车在高速公路、城市快速路以外的道路上行驶超过规定时速10%未达20%的', 'wzcity': '广东深圳', 'handled': '0', 'money': '0', 'fen': '3', 'code': '13501', 'area': '省道22179公里500米' }, { 'archiveno': '', # 文书编号 'date': '2017-11-25 15:42:00', # 违章时间 'act': '违反禁令标志指示', # 违章行为 'wzcity': '', # 违章行为发生的城市 'handled': '0', # 是否处理,1处理 0未处理 空未知 'money': '0', # 违章罚款(仅供参考,不一定有值) 'fen': '3', # 违章扣分(仅供参考,不一定有值) 'code': '1344', # 违章代码(仅供参考,不一定有值) 'area': '沪昆高速1073公里600米处东往西' # 违章地点 } ], 'city': 'JX_YICHUN_J', 'hphm': '赣CX3706', 'province': 'JX', 'hpzl': '01' } } """ if r['error_code'] != 0: mes['message'] = r['reason'] else: result = r['result'] """ class ViolationQueryResult(mongo_db.BaseDoc): _table_name = "violation_query_result_info" type_dict = dict() type_dict["_id"] = ObjectId # id 唯一 type_dict['user_id'] = ObjectId # 关联用户的id type_dict['generator_id'] = ObjectId # 关联查询器的id type_dict['amount'] = int # 截止到目前一共多少次违章? type_dict['total_fine'] = float # 未处理违章总罚款 type_dict['total_points'] = int # 未处理违章总扣分 type_dict['untreated'] = int # 未处理违章条数 type_dict['create_date'] = datetime.datetime # 查询结果创建时间 type_dict['violations'] = list # 违章记录,是DBRef的数组 class ViolationRecode(mongo_db.BaseDoc): _table_name = "violation_info" type_dict = dict() type_dict["_id"] = ObjectId # id 唯一 type_dict['user_id'] = ObjectId # 关联用户的id type_dict['plate_number'] = str # 违章时的车牌号 type_dict["code"] = str # 违章编码,唯一,非违章条例码 type_dict["time"] = datetime.datetime # 违章时间 type_dict["update_time"] = datetime.datetime # 记录变更时间 type_dict["fine"] = float # 罚款金额 type_dict["address"] = str # 违章地址 type_dict["reason"] = str # 违章处理原因 type_dict["point"] = int # 违章扣分 type_dict["province"] = str # 省份 type_dict["city"] = str # 城市 type_dict["service_fee"] = float # 服务费 type_dict["violation_num"] = str # 违章编码 type_dict["can_select"] = int # 能否勾选办理:0不可勾选, 1可勾选。 type_dict["process_status"] = str # 违章处理状态:1:未处理,2:处理中,3:已处理,4:不支持 type_dict["payment_status"] = str # 违章缴费状态 不返回表示无法获取该信息,1-未缴费 2-已缴 type_dict['position_id'] = ObjectId # 违章地址的经纬度信息的id,指向Position类 """ vio_list = result.get('lists') if isinstance(vio_list, list): data = dict() # 最后返回的数据 amount = 0 # 违章总数 untreated = 0 # 未处理违章条数 total_fine = 0.0 # 未处理违章总罚款 total_points = 0 # 未处理违章总扣分 violations = list() # 违章记录容器 for vio in vio_list: """ vio = { 'archiveno': '', # 文书编号 'date': '2017-11-25 15:42:00', # 违章时间 'act': '违反禁令标志指示', # 违章行为 'wzcity': '', # 违章行为发生的城市 'handled': '0', # 是否处理,1处理 0未处理 空未知 'money': '0', # 违章罚款(仅供参考,不一定有值) 'fen': '3', # 违章扣分(仅供参考,不一定有值) 'code': '1344', # 违章代码(仅供参考,不一定有值) 'area': '沪昆高速1073公里600米处东往西' # 违章地点 } """ amount += 1 handled = vio['handled'] _id = vio.get('archiveno') # 文书编号,页就是以前的违章唯一编号,不一定有 code = vio.get('code') money = vio.get("money") try: money = float(money) except Exception as e: logger.exception(e) money = None fen = vio.get("fen") try: fen = int(fen) except Exception as e: logger.exception(e) fen = None """ 聚合返回:是否处理,1处理 0未处理 空未知 接口要求,违章处理状态:1:未处理,2:处理中,3:已处理,4:不支持 """ payment_status = 1 if handled == "0": """未处理""" handled = 1 untreated += 1 if money is not None: total_fine += money if fen is not None: total_points += fen elif handled == "1": handled = 0 payment_status = 2 else: handled = 4 temp = { "time": mongo_db.get_datetime_from_str(vio['date']), # 违章时间 "city": '' if vio.get('wzcity') else vio['wzcity'], # 违章城市 "plate_number": plate_number, # 车牌 "_id": _id, # 文书编号,就是以前的违章唯一编号,不一定有 "code": code, # 违章代码,不一定有 "fine": money, # 罚款,不一定有 "point": fen, # 扣分,不一定有 "reason": vio['act'], # 违章原因 "address": vio['area'], # 违章地址 "process_status": handled, # 违章状态,是否处理,int类型 "payment_status": payment_status # 支付状态,是否支付,int类型 } temp = {k: v for k, v in temp.items()} violations.append(temp) data['amount'] = amount data['plate_number'] = plate_number data['untreated'] = untreated data['total_fine'] = total_fine data['total_points'] = total_points data['violations'] = violations mes['data'] = data else: pass return mes
def send_reg_info(group_by: str, info: dict) -> dict: """ 发送注册信息的钉订消息到各个大部群 :param group_by: :param info: :return: """ mes = {"message": "success"} if group_by.startswith("01"): key = "01" elif group_by.startswith("02"): key = "02" elif group_by.startswith("03"): key = "03" elif group_by.startswith("04"): key = "04" elif group_by.startswith("05"): key = "05" else: key = None if key is None: title = "无效的分组信息: {}, {}".format(group_by, datetime.datetime.now()) send_mail(title=title) print(title) return mes else: sent_dict = dict() sent_dict['kwargs'] = {"info": info, "group_by": group_by} sent_dict['result'] = 'success' token = url_map[key] data = json.dumps(info) headers = {'Content-Type': 'application/json'} base_url = "https://oapi.dingtalk.com/robot/send?access_token=" robot_url = "{}{}".format(base_url, token) try: r = requests.post(robot_url, data=data, headers=headers, timeout=2) status = r.status_code if status != 200: ms = "{} 服务器返回了错误的代码:{}".format(robot_url, status) logger.exception(ms) sent_dict['result'] = ms else: pass except Exception as e: reason = str(e) mes['message'] = "error" mes['reason'] = reason sent_dict['result'] = reason finally: sent_dict['time'] = datetime.datetime.now() col = DDSentResult.get_collection(write_concern={ "w": 1, "j": True }) r = col.insert_one(document=sent_dict) if hasattr(r, "inserted_id"): pass else: ms = "向dd_sent_result表写入保存结果的时候失败,{}".format(sent_dict) logger.exception(msg=ms) return mes
def get_browser(headless: bool = True, browser_class: int = 1) -> Firefox: """ 获取一个浏览器 :param headless: :param browser_class: 浏览器种类,0是谷歌, 1 是火狐, 服务器端不能使用谷歌 :return: """ """ firefox的headless浏览器 因为headless的浏览器的语言跟随操作系统,为了保证爬回来的数据是正确的语言, 这里必须设置浏览器的初始化参数, 注意,使用headless必须先安装对应浏览器正常的版本,然后再安装headless版本 比如火狐的headless 下载火狐的geckodriver驱动。(当前文件夹下已经有一个了)地址是: https://github.com/mozilla/geckodriver/releases 下载后解压是一个geckodriver 文件。拷贝到/usr/local/bin目录下,然后加上可执行的权限 sudo chmod +x /usr/local/bin/geckodriver chrome的headless浏览器 https://chromedriver.storage.googleapis.com/index.html?path=2.35/ 你也可以自行搜索chromedriver的下载地址,解压是个可执行文件,放到chrome的目录即可. 一般ubuntu下面,chrome的目录是/opt/google/chrome/ 据说使用root权限运行的话,chrome的headless浏览器会报异常.而firefox的headless浏览器不会! """ if browser_class == 1: profile = FirefoxProfile() profile.set_preference("intl.accept_languages", "zh-cn") options = FirefoxOptions() options.add_argument("--headless") if headless: try: browser = Firefox(firefox_profile=profile, executable_path=firefox_driver, firefox_options=options) except Exception as e: title = "{} Firefox headless浏览器打开失败".format( datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) logger.exception(e) raise e else: try: browser = Firefox( firefox_profile=profile, executable_path=firefox_driver, ) except Exception as e: title = "{} Firefox headless浏览器打开失败".format( datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) logger.exception(e) raise e else: options = ChromeOptions() options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"]) if headless: options.add_argument("--headless") try: browser = Chrome(executable_path=chrome_driver, chrome_options=options) except Exception as e: title = "{} Chrome headless浏览器打开失败".format( datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) logger.exception(e) raise e else: try: browser = Chrome(executable_path=chrome_driver, chrome_options=options) except Exception as e: title = "{} Chrome headless浏览器打开失败".format( datetime.datetime.now()) content = "错误原因是:{}".format(e) send_mail(title=title, content=content) # 这是我自定义的方法 logger.exception(e) raise e return browser
async def new_order_message2(t_id: str, t_name: str, product: str, order_type: str, enter_time: str, enter_price: (str, float, int), exit_time: str = None, exit_price: (str, float, int) = None) -> bool: """ 新订单模板消息,使用批量发送. 2018-10-18启用 待发送的模板消息字典 格式: 2018-10-18之前: {'t_id': '5b8c5452dbea62189b5c28f9', 'order_type': '开仓'} 2018-10-18之后: { 'product': '原油', 'order_type': '开仓', 'enter_time': datetime.datetime(2018, 10, 18, 3, 53, 11, 670692), 'exit_time': datetime.datetime(2018, 10, 18, 3, 53, 11, 670692), # 只有平仓才有 't_id': 5b8c5452dbea62189b5c28f9, 't_name': 非功, 'enter_price': 69.955, 'exit_price': 69.955, # 只有平仓才有 } :param t_id: :param t_name: :param product: :param order_type: :param enter_time: :param enter_price: :param exit_time: :param exit_price: :return: """ ms = "new_order_message2正在处理发送请求:t_name={}, t_id={}".format(t_name, t_id) logger.info(ms) # send_mail(title="func begin...", content='{}'.format(datetime.datetime.now())) ses = mongo_db.get_conn("teacher") t_id = ObjectId(t_id) if isinstance(t_id, str) else t_id f = {"_id": t_id} p = {"_id", "name"} t = ses.find_one(filter=f, projection=p) if t is None: ms = "发送模板消息出错,无效的t_id:{}".format(t_id) logger.exception(msg=ms) send_mail(title=ms) return False else: t_id = t['_id'] t_name = t['name'] f = {"follow": {"$elemMatch": {"$in": [t_id]}}} p = ['_id', "openid", "nick_name"] now = datetime.datetime.now() ses = mongo_db.get_conn(table_name="wx_user") us = ses.find(filter=f, projection=p) us = [x for x in us] us_l = len(us) # send_mail(title="if begin ...", content='us_l={}, {}'.format(us_l, datetime.datetime.now())) ms = "准备发送{}条模板消息,查询条件={}".format(us_l, f) # send_mail(title=ms) logger.info(msg=ms) if us_l > 0: u = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}".format( AccessToken.get_token()) info = {"t_id": t_id, "t_name": t_name, "time": now} # send_mail(title="async begin ...", content='{}'.format(datetime.datetime.now())) async with aiohttp.ClientSession() as session: for x in us: openid = x['openid'] nick_name = x['nick_name'] info['openid'] = openid info['nick_name'] = nick_name # send_mail(title="for begin ...", content='{}'.format(datetime.datetime.now())) template_id = 'i6NuPzoeW1HqSNSf97KwDn3AVQk1_jmUHKoHtlCxA7k' args = { "touser": openid, "template_id": template_id, "url": "http://wx.91master.cn/user/html/currentCrunchy.html?t_id={}" .format( str(t_id) if isinstance(t_id, ObjectId) else t_id), "data": { "first": { "value": "你关注的{}老师有新的操作..".format(t_name), "color": "grey", }, "keyword1": { "value": product, # 交易品种 "color": "#82B6F4" }, "keyword2": { "value": enter_time, # 开仓时间 "color": "#82B6F4" }, "keyword3": { "value": "建仓" if order_type == "开仓" else order_type, "color": "#82B6F4", }, "keyword4": { "value": enter_price, # 开仓价格 "color": "#82B6F4" }, "keyword5": { "value": exit_price, # 平仓价格 "color": "#82B6F4" }, "remark": { "value": "此信息代表{}老师个人观点,仅供参考.点击“详情”查看完整信息".format( t_name), "color": "#dc1c1c" } } } title = "发送给{}的模板消息".format(nick_name) content = "模板消息内容 data={}".format(args) ms = "{} | {}".format(title, content) logger.info(ms) # send_mail(title=title, content=content) async with session.post(url=u, data=json.dumps(args), timeout=5) as response: resp = await response.json() if isinstance(resp, dict): info['return'] = "success" info.update(resp) else: info['return'] = "error" info['_id'] = ObjectId() info['args'] = args info['time'] = now ses = TemplateMessageResponse.get_collection() ses.insert_one(document=info) return True else: return False