dy-dashboard/update_data.py
2026-10-28 11:14:17 +08:00

161 lines
5.4 KiB
Python
Raw Permalink 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.

#!/usr/bin/env python3
"""钉盘数据增量更新 - 下载新增CSV并导入数据库"""
import os, sys, json, subprocess, urllib.request, time
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CSV_DIR = os.path.join(BASE_DIR, "tmp_csv")
os.makedirs(CSV_DIR, exist_ok=True)
def log(m): print(f"[{time.strftime('%H:%M:%S')}] {m}")
def dws(cmd):
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=60)
try: return json.loads(r.stdout)
except: return {}
def download_file(node_id, filename):
"""下载单个文件"""
dest = os.path.join(CSV_DIR, filename)
if os.path.exists(dest):
log(f" 已存在,跳过: {filename}")
return True
log(f" 下载 {filename} ...")
# 用 --output 获取下载链接
tmp = f"/tmp/dld_{int(time.time())}_{filename}"
info = dws(f'dws doc download --node "{node_id}" --output "{tmp}" --format json')
if not info.get("success"):
log(f" ❌ 获取下载链接失败: {filename}")
return False
url = info.get("resourceUrl", "")
if not url:
log(f" ❌ 无下载链接: {filename}")
return False
try:
urllib.request.urlretrieve(url, dest)
size = os.path.getsize(dest)
log(f" ✅ {filename} ({size:,} bytes)")
# 清理临时文件
if os.path.exists(tmp): os.remove(tmp)
return True
except Exception as e:
log(f" ❌ 下载失败: {filename} - {e}")
return False
def get_all_nodes(folder_id):
"""获取文件夹下所有文件(自动翻页)"""
all_nodes = []
page_token = None
while True:
cmd = f'dws doc list --folder "{folder_id}" --format json'
if page_token:
cmd += f' --page-token "{page_token}"'
result = dws(cmd)
nodes = result.get('nodes', [])
all_nodes.extend(nodes)
if not result.get('hasMore'):
break
page_token = result.get('nextPageToken')
if not page_token:
break
return all_nodes
# ========== 1. 下载日出库数据(06-02 ~ 06-05)==========
log("=" * 60)
log("第一步:下载日出库 CSV 文件 (06-02 ~ 06-05)")
OUTBOUND_FOLDER = "3NwLYZXWynyBjRB4tZjwNxDvVkyEqBQm"
outbound_nodes = get_all_nodes(OUTBOUND_FOLDER)
log(f"日出库文件夹共 {len(outbound_nodes)} 个文件")
target_dates = ['20260602', '20260603', '20260604', '20260605']
downloaded_outbound = 0
for n in outbound_nodes:
name = n['name']
node_id = n.get('nodeId', '')
if any(name.startswith(d) for d in target_dates):
clean_name = name.strip().replace(' ', '')
if not clean_name.endswith('.csv'):
clean_name += '.csv'
if download_file(node_id, clean_name):
downloaded_outbound += 1
log(f"日出库下载完成: {downloaded_outbound} 个文件")
# ========== 2. 下载库存数据(06-08)==========
log("")
log("=" * 60)
log("第二步:下载库存 CSV 文件 (06-08)")
INVENTORY_FOLDER = "NkDwLng8ZLGrXmrnFxYq3vRqVKMEvZBY"
inventory_nodes = get_all_nodes(INVENTORY_FOLDER)
log(f"库存文件夹共 {len(inventory_nodes)} 个文件")
downloaded_inventory = 0
for n in inventory_nodes:
name = n['name']
node_id = n.get('nodeId', '')
if name.startswith('20260608') and name.endswith('.csv'):
if download_file(node_id, name):
downloaded_inventory += 1
log(f"库存下载完成: {downloaded_inventory} 个文件")
# ========== 3. 导入数据到MySQL ==========
log("")
log("=" * 60)
log("第三步:导入数据到数据库")
log("导入日出库数据...")
r = subprocess.run(
f"cd {BASE_DIR} && python3 reimport.py",
shell=True, capture_output=True, text=True, timeout=600
)
if r.returncode == 0:
log("✅ 日出库导入成功")
else:
log(f"⚠️ 日出库导入异常: {r.stderr[-300:]}")
for line in r.stdout.strip().split('\n')[-10:]:
log(f" {line}")
log("导入库存数据...")
r = subprocess.run(
f"cd {BASE_DIR} && python3 batch_import_inventory.py",
shell=True, capture_output=True, text=True, timeout=600
)
if r.returncode == 0:
log("✅ 库存导入成功")
else:
log(f"⚠️ 库存导入异常: {r.stderr[-300:]}")
for line in r.stdout.strip().split('\n')[-10:]:
log(f" {line}")
# ========== 4. 验证数据 ==========
log("")
log("=" * 60)
log("第四步:验证数据")
import pymysql
from config import DB_CONFIG
try:
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor() as cur:
cur.execute("SELECT MIN(日期) AS min_d, MAX(日期) AS max_d, COUNT(*) AS cnt FROM daily_outbound")
r = cur.fetchone()
log(f"日出库: {r[0]} ~ {r[1]}, 共 {r[2]} 条")
cur.execute("SELECT MIN(data_date) AS min_d, MAX(data_date) AS max_d, COUNT(*) AS cnt FROM inventory_detail")
r = cur.fetchone()
log(f"库存: {r[0]} ~ {r[1]}, 共 {r[2]} 条")
conn.close()
log("✅ 数据验证通过")
except Exception as e:
log(f"⚠️ 验证失败: {e}")
# ========== 5. 重启服务 ==========
log("")
log("=" * 60)
log("第五步:重启服务刷新缓存")
os.system("kill $(lsof -t -i:18888) 2>/dev/null; sleep 2")
os.system(f"cd {BASE_DIR} && nohup /home/gxd/.local/bin/gunicorn -w 4 -b 0.0.0.0:18888 --timeout 120 --max-requests 800 --max-requests-jitter 100 --access-logfile logs/access.log --error-logfile logs/error.log app:app > logs/startup.log 2>&1 &")
log("✅ 服务已重启,数据同步完成")