Files
eu_active_script/hang/demo06092.py

207 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import pandas as pd
import requests
import json
from datetime import datetime
from sqlalchemy import create_engine
from urllib.parse import quote_plus
import logging
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def get_access_token():
"""获取飞书访问令牌[1,7](@ref)"""
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"}
try:
response = requests.post(api_token_url, json=api_post_data, timeout=10)
response.raise_for_status()
if response.json().get("code") == 0:
return response.json()["tenant_access_token"]
else:
raise Exception(f"获取Token失败: {response.text}")
except Exception as e:
logging.error(f"获取飞书Token异常: {str(e)}")
raise
def overwrite_data(spreadsheet_token, values, access_token=None):
"""覆盖写入数据到飞书多维表格[1,6](@ref)"""
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
}
}
try:
response = requests.put(url, json=post_data, headers=headers, timeout=15)
response.raise_for_status()
return response
except Exception as e:
logging.error(f"写入飞书表格失败: {str(e)}")
raise
# 数据库连接配置
DB_CONFIG = {
'host': 'eutsp-prod.mysql.germany.rds.aliyuncs.com',
'port': 3306,
'user': 'international_tsp_eu_r',
'password': 'ZXhBgo1TB2XbF3kP',
'database': 'chery_international_tsp_eu'
}
# 创建SQLAlchemy引擎解决pandas警告问题
safe_password = quote_plus(DB_CONFIG['password'])
engine = create_engine(
f"mysql+pymysql://{DB_CONFIG['user']}:{safe_password}@{DB_CONFIG['host']}:{DB_CONFIG['port']}/{DB_CONFIG['database']}",
pool_recycle=3600,
pool_pre_ping=True,
pool_size=5,
max_overflow=10
)
def fetch_data_from_db():
"""从数据库执行SQL查询获取数据使用SQLAlchemy引擎"""
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, engine)
except Exception as e:
logging.error(f"数据库查询失败: {str(e)}")
raise
def send_feishu_message(webhook_url, message, spreadsheet_token=None, retry=2):
"""
通过Webhook发送飞书消息支持添加多维表格链接[2,8](@ref)
:param webhook_url: 机器人Webhook地址
:param message: 要发送的文本内容
:param spreadsheet_token: 多维表格ID可选
:param retry: 重试次数
"""
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}}
for attempt in range(retry):
try:
response = requests.post(webhook_url, headers=headers, data=json.dumps(payload), timeout=10)
response.raise_for_status()
return response.json()
except Exception as e:
logging.warning(f"飞书消息发送失败(尝试 {attempt + 1}/{retry}): {str(e)}")
if attempt < retry - 1:
time.sleep(2) # 等待后重试
raise Exception(f"飞书消息发送失败,重试{retry}次后仍不成功")
if __name__ == '__main__':
# 配置参数
SPREADSHEET_ID = "MIqssvuB3h3XmgtkI26cBX7Angc"
WEBHOOK_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/d82e4ada-8f78-40ae-b98e-75af0c448c95"
try:
logging.info("开始数据同步流程...")
# 1. 从数据库获取数据
df = fetch_data_from_db()
logging.info(f"成功获取{len(df)}条车辆数据")
# 2. 处理数据
df['active_date'] = pd.to_datetime(df['active_date'], errors='coerce')
active_df = df[df['active_status'] == 'active']
logging.info(f"有效激活数据: {len(active_df)}")
# 3. 按天统计激活数
daily_count = active_df.groupby(active_df['active_date'].dt.date).size().reset_index(name='active_count')
values = [[str(d), str(c)] for d, c in daily_count.values.tolist()] # 确保值为字符串类型
logging.info(f"生成{len(values)}条日期统计记录")
# 4. 覆盖写入多维表格
response = overwrite_data(SPREADSHEET_ID, values)
if response.status_code == 200:
logging.info("数据成功写入飞书多维表格")
# 5. 构建通知消息
current_time = datetime.now().strftime("%Y-%m-%d %H:%M")
today_count = daily_count[daily_count['active_date'] == datetime.now().date()]
weekly_count = daily_count[daily_count['active_date'] >= (datetime.now() - pd.Timedelta(days=7)).date()]
stats_summary = f"• 今日激活车辆: {today_count['active_count'].values[0] if not today_count.empty else 0}\n"
stats_summary += f"• 本周激活车辆: {weekly_count['active_count'].sum()}\n"
stats_summary += f"• 累计激活车辆: {len(active_df)}"
message = f"🚗 车辆数据同步完成 ✅\n"
message += f"⏰ 时间: {current_time}\n"
message += f"📊 统计摘要:\n{stats_summary}\n"
# 6. 发送包含多维表格链接的通知
result = send_feishu_message(WEBHOOK_URL, message, SPREADSHEET_ID)
logging.info(f"飞书消息发送成功: {result}")
else:
error_msg = f"表格写入失败: {response.status_code} - {response.text}"
logging.error(error_msg)
error_message = f"❌ 数据同步失败\n{error_msg}"
send_feishu_message(WEBHOOK_URL, error_message)
except Exception as e:
error_message = f"❌ 数据同步异常: {str(e)}"
logging.exception("程序执行异常")
send_feishu_message(WEBHOOK_URL, error_message)