feat: 添加热点股追踪数据导出/导入脚本
This commit is contained in:
Executable
+236
@@ -0,0 +1,236 @@
|
||||
#!/bin/bash
|
||||
# 从Docker容器导出热点股数据
|
||||
|
||||
set -e
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
CONTAINER_NAME="auv"
|
||||
DB_PATH="/app/backend/data/stock_data.db"
|
||||
|
||||
# 检查容器是否运行
|
||||
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
||||
echo -e "${RED}❌ 容器 ${CONTAINER_NAME} 未运行${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查数据库是否存在
|
||||
if ! docker exec "$CONTAINER_NAME" test -f "$DB_PATH"; then
|
||||
echo -e "${RED}❌ 数据库文件不存在:$DB_PATH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 显示帮助
|
||||
show_help() {
|
||||
echo "用法:"
|
||||
echo " $0 export [日期] - 导出指定日期的数据(默认:2026-08-20)"
|
||||
echo " $0 import <文件> - 导入数据文件到容器"
|
||||
echo " $0 list - 列出所有有数据的日期"
|
||||
echo " $0 backup - 备份整个数据库"
|
||||
echo " $0 shell - 进入容器的Python shell"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 export 2026-08-20"
|
||||
echo " $0 import hotspot_2026-08-20.json"
|
||||
echo " $0 backup"
|
||||
}
|
||||
|
||||
# 导出数据
|
||||
export_data() {
|
||||
local date="${1:-2026-08-20}"
|
||||
local output_file="hotspot_${date}.json"
|
||||
|
||||
echo -e "${YELLOW}📤 从容器导出 $date 的热点股数据...${NC}"
|
||||
|
||||
# 在容器内执行导出命令
|
||||
docker exec "$CONTAINER_NAME" python3 -c "
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
from database import get_connection, dict_from_row
|
||||
import json
|
||||
|
||||
date = '$date'
|
||||
conn = get_connection()
|
||||
try:
|
||||
themes = conn.execute('SELECT * FROM daily_top_themes WHERE trade_date = ? ORDER BY rank ASC', (date,)).fetchall()
|
||||
core_stocks = conn.execute('SELECT * FROM daily_core_stocks WHERE trade_date = ? ORDER BY rank ASC', (date,)).fetchall()
|
||||
stock_themes = conn.execute('SELECT * FROM daily_core_stock_themes WHERE trade_date = ?', (date,)).fetchall()
|
||||
|
||||
data = {
|
||||
'version': '1.0',
|
||||
'trade_date': date,
|
||||
'themes': [dict_from_row(r) for r in themes],
|
||||
'core_stocks': [dict_from_row(r) for r in core_stocks],
|
||||
'stock_themes': [dict_from_row(r) for r in stock_themes],
|
||||
}
|
||||
data['stats'] = {
|
||||
'theme_count': len(data['themes']),
|
||||
'core_stock_count': len(data['core_stocks']),
|
||||
'stock_theme_count': len(data['stock_themes']),
|
||||
}
|
||||
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
finally:
|
||||
conn.close()
|
||||
" > "$output_file"
|
||||
|
||||
if [ -f "$output_file" ]; then
|
||||
echo -e "${GREEN}✅ 导出完成:$output_file${NC}"
|
||||
echo "文件大小:$(du -h "$output_file" | cut -f1)"
|
||||
else
|
||||
echo -e "${RED}❌ 导出失败${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 导入数据
|
||||
import_data() {
|
||||
local file="$1"
|
||||
|
||||
if [ -z "$file" ]; then
|
||||
echo -e "${RED}❌ 请指定要导入的文件${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
echo -e "${RED}❌ 文件不存在:$file${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}📥 导入数据到容器:$file${NC}"
|
||||
|
||||
# 复制文件到容器
|
||||
docker cp "$file" "$CONTAINER_NAME:/tmp/import_data.json"
|
||||
|
||||
# 在容器内执行导入
|
||||
docker exec "$CONTAINER_NAME" python3 -c "
|
||||
import sys
|
||||
import json
|
||||
sys.path.insert(0, '/app')
|
||||
from database import get_connection
|
||||
|
||||
with open('/tmp/import_data.json', 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
date = data['trade_date']
|
||||
print(f'📅 导入日期:{date}')
|
||||
print(f' 题材数量:{len(data[\"themes\"])}')
|
||||
print(f' 核心股票:{len(data[\"core_stocks\"])}')
|
||||
print(f' 股票-题材关联:{len(data[\"stock_themes\"])}')
|
||||
|
||||
conn = get_connection()
|
||||
try:
|
||||
for item in data['themes']:
|
||||
item.pop('id', None)
|
||||
item.pop('created_at', None)
|
||||
conn.execute(
|
||||
'INSERT OR IGNORE INTO daily_top_themes (trade_date, theme_code, theme_name, bf3, hot_rank, rank) VALUES (?,?,?,?,?,?)',
|
||||
(item['trade_date'], item['theme_code'], item['theme_name'], item['bf3'], item['hot_rank'], item['rank']),
|
||||
)
|
||||
|
||||
for item in data['core_stocks']:
|
||||
item.pop('id', None)
|
||||
item.pop('created_at', None)
|
||||
conn.execute(
|
||||
'INSERT OR IGNORE INTO daily_core_stocks (trade_date, stock_code, stock_name, f3, cover_count, rank) VALUES (?,?,?,?,?,?)',
|
||||
(item['trade_date'], item['stock_code'], item['stock_name'], item['f3'], item['cover_count'], item['rank']),
|
||||
)
|
||||
|
||||
for item in data['stock_themes']:
|
||||
item.pop('id', None)
|
||||
item.pop('created_at', None)
|
||||
conn.execute(
|
||||
'INSERT OR IGNORE INTO daily_core_stock_themes (trade_date, stock_code, theme_code, theme_name) VALUES (?,?,?,?)',
|
||||
(item['trade_date'], item['stock_code'], item['theme_code'], item['theme_name']),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
print(f'\\n✅ 导入成功:{date}')
|
||||
except Exception as e:
|
||||
conn.rollback()
|
||||
print(f'\\n❌ 导入失败:{e}')
|
||||
finally:
|
||||
conn.close()
|
||||
"
|
||||
}
|
||||
|
||||
# 列出日期
|
||||
list_dates() {
|
||||
echo -e "${YELLOW}📅 列出容器中的日期...${NC}"
|
||||
docker exec "$CONTAINER_NAME" python3 -c "
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
from database import get_connection
|
||||
|
||||
conn = get_connection()
|
||||
try:
|
||||
rows = conn.execute('SELECT DISTINCT trade_date FROM daily_core_stocks ORDER BY trade_date DESC').fetchall()
|
||||
if rows:
|
||||
print('📅 数据库中的日期:')
|
||||
for row in rows:
|
||||
print(f' {row[\"trade_date\"]}')
|
||||
else:
|
||||
print('📭 数据库中暂无数据')
|
||||
finally:
|
||||
conn.close()
|
||||
"
|
||||
}
|
||||
|
||||
# 备份数据库
|
||||
backup_database() {
|
||||
local timestamp=$(date +%Y%m%d_%H%M%S)
|
||||
local backup_file="stock_data_${timestamp}.db"
|
||||
|
||||
echo -e "${YELLOW}💾 备份数据库...${NC}"
|
||||
docker cp "$CONTAINER_NAME:$DB_PATH" "$backup_file"
|
||||
|
||||
if [ -f "$backup_file" ]; then
|
||||
echo -e "${GREEN}✅ 备份完成:$backup_file${NC}"
|
||||
echo "文件大小:$(du -h "$backup_file" | cut -f1)"
|
||||
else
|
||||
echo -e "${RED}❌ 备份失败${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 进入Python shell
|
||||
enter_shell() {
|
||||
echo -e "${YELLOW}🐍 进入容器Python shell...${NC}"
|
||||
docker exec -it "$CONTAINER_NAME" python3 -c "
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
from database import get_connection
|
||||
print('Python shell 已启动')
|
||||
print('可用变量:')
|
||||
print(' conn - 数据库连接')
|
||||
print(' get_connection - 获取新连接函数')
|
||||
print()
|
||||
conn = get_connection()
|
||||
"
|
||||
}
|
||||
|
||||
# 主逻辑
|
||||
case "${1:-help}" in
|
||||
export)
|
||||
export_data "$2"
|
||||
;;
|
||||
import)
|
||||
import_data "$2"
|
||||
;;
|
||||
list)
|
||||
list_dates
|
||||
;;
|
||||
backup)
|
||||
backup_database
|
||||
;;
|
||||
shell)
|
||||
enter_shell
|
||||
;;
|
||||
*)
|
||||
show_help
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user