import pandas as pd import pymysql from sqlalchemy import create_engine import requests import json import pandas as pd from datetime import datetime import os def get_access_token(): """获取飞书访问令牌""" api_token_url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/" api_post_data = {"app_id": "cli_a8b50ec0eed1500d", "app_secret": "ccxkE7ZCFQZcwkkM1rLy0ccZRXYsT2xK"} response = requests.post(api_token_url, json=api_post_data) if response.status_code == 200 and response.json().get("code") == 0: return response.json()["tenant_access_token"] else: raise Exception(f"获取 Token 失败: {response.text}") def overwrite_data(spreadsheet_token, values, access_token=None): """覆盖写入数据到飞书多维表格""" if not access_token: access_token = get_access_token() url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/values" headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json; charset=utf-8", } row_count = len(values) + 1 range_str = f"46ea20!A1:B{row_count}" post_data = { "valueRange": { "range": range_str, "values": values } } response = requests.put(url, json=post_data, headers=headers) return response # 返回响应对象以便检查状态 # 数据库连接配置 DB_CONFIG = { 'host': 'eutsp-prod.mysql.germany.rds.aliyuncs.com', 'port': 3306, 'user': 'international_tsp_eu_r', 'password': 'ZXhBgo1TB2XbF3kP', 'database': 'chery_international_tsp_eu' } def fetch_data_from_db(): """从数据库执行SQL查询获取数据""" connection = pymysql.connect(**DB_CONFIG) try: sql_query = """ SELECT v_vehicle_info.VIN AS car_vins, CASE v_sim_info.STATE WHEN 2 THEN 'active' ELSE 'no_active' END AS active_status, v_vehicle_info.MATERIAL_ID as MATERIAL, v_vehicle_info.SALES_TERRITORY as Area, v_sim_info.ACTIVATION_DATE as active_date FROM v_vehicle_info JOIN v_tbox_info USING (VIN) JOIN v_sim_info USING (SN); """ return pd.read_sql(sql_query, connection) finally: connection.close() def send_feishu_message(webhook_url, message, spreadsheet_token=None): """ 通过Webhook发送飞书消息,支持添加多维表格链接 :param webhook_url: 机器人Webhook地址 :param message: 要发送的文本内容 :param spreadsheet_token: 多维表格ID(可选) """ headers = {'Content-Type': 'application/json'} # 如果有提供多维表格ID,添加表格链接按钮 if spreadsheet_token: # 创建多维表格链接 spreadsheet_url = f"https://my-ichery.feishu.cn/sheets/{spreadsheet_token}" # 使用交互式消息卡片格式 payload = { "msg_type": "interactive", "card": { "config": { "wide_screen_mode": True }, "elements": [{ "tag": "div", "text": { "content": message, "tag": "lark_md" } }, { "actions": [{ "tag": "button", "text": { "content": "查看多维表格", "tag": "plain_text" }, "type": "primary", "url": spreadsheet_url }], "tag": "action" }], "header": { "title": { "content": "数据同步完成通知", "tag": "plain_text" }, "template": "green" } } } else: # 普通文本消息 payload = { "msg_type": "text", "content": {"text": message} } response = requests.post(webhook_url, headers=headers, data=json.dumps(payload)) return response.json() if __name__ == '__main__': # 配置参数 SPREADSHEET_ID = "MIqssvuB3h3XmgtkI26cBX7Angc" WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/d82e4ada-8f78-40ae-b98e-75af0c448c95" try: # 1. 从数据库获取数据 df = fetch_data_from_db() # 2. 处理数据 df['active_date'] = pd.to_datetime(df['active_date'], errors='coerce') active_df = df[df['active_status'] == 'active'] # 3. 按天统计活跃数 daily_count = active_df.groupby(active_df['active_date'].dt.date).size().reset_index(name='active_count') values = [[str(d), c] for d, c in daily_count.values.tolist()] # 4. 覆盖写入多维表格 response = overwrite_data(SPREADSHEET_ID, values) if response.status_code == 200: # 5. 构建通知消息 current_time = datetime.now().strftime("%Y-%m-%d %H:%M") stats_summary = f"• 今日活跃车辆: {daily_count['active_count'].iloc[-1] if len(daily_count) > 0 else 0}\n" stats_summary += f"• 本周活跃车辆: {daily_count[daily_count['active_date'] >= (datetime.now() - pd.Timedelta(days=7)).date()]['active_count'].sum()}\n" stats_summary += f"• 累计活跃车辆: {len(active_df)}" message = f"🚗 车辆数据同步完成 ✅\n" message += f"⏰ 时间: {current_time}\n" message += f"📊 统计摘要:\n{stats_summary}\n" message += "[安全关键词:告警]" # 6. 发送包含多维表格链接的通知 result = send_feishu_message(WEBHOOK_URL, message, SPREADSHEET_ID) print("飞书消息发送成功:", result) else: error_msg = f"表格写入失败: {response.status_code} - {response.text}" error_message = f"❌ 数据同步失败\n{error_msg}\n[安全关键词:告警]" send_feishu_message(WEBHOOK_URL, error_message) print(error_msg) except Exception as e: error_message = f"❌ 数据同步异常: {str(e)}\n[安全关键词:告警]" send_feishu_message(WEBHOOK_URL, error_message) print("发生异常:", str(e))