This commit is contained in:
HuangHai
2026-01-15 07:42:27 +08:00
parent a61e18bf26
commit 9cc78ff125
2 changed files with 71 additions and 36 deletions

View File

@@ -2,22 +2,23 @@ import asyncio
import os import os
import sys import sys
import logging import logging
from typing import List, Dict
# 确保项目根目录在 sys.path 中,并且优先于外部同名模块 # 确保项目根目录在 sys.path 中,并且优先于外部同名模块
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if project_root not in sys.path: if project_root not in sys.path:
sys.path.insert(0, project_root) sys.path.insert(0, project_root)
from Util import Win32Patch from Util import Win32Patch
from DbKit.Db import Db from DbKit.Db import Db
from Util.RedisKit import RedisKit from Util.RedisKit import RedisKit
from sqlalchemy.sql import text from sqlalchemy.sql import text
try: try:
from Config.Config import DB_URL from Config.Config import DB_URL
except ModuleNotFoundError: except ModuleNotFoundError:
import importlib.util import importlib.util
_root_dir_cfg = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) _root_dir_cfg = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_config_path_cfg = os.path.join(_root_dir_cfg, "Config", "Config.py") _config_path_cfg = os.path.join(_root_dir_cfg, "Config", "Config.py")
_spec_cfg = importlib.util.spec_from_file_location("project_config_fallback", _config_path_cfg) _spec_cfg = importlib.util.spec_from_file_location("project_config_fallback", _config_path_cfg)
_cfg_mod = importlib.util.module_from_spec(_spec_cfg) _cfg_mod = importlib.util.module_from_spec(_spec_cfg)
@@ -27,20 +28,26 @@ except ModuleNotFoundError:
# 配置日志 # 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger("ClearAiTeJiYiChong") logger = logging.getLogger("T5_ClearHistory")
async def main(): # 供应商配置映射
VENDORS = {
"1": {"name": "特来电", "redis_pattern": "crawled:tld:*"},
"2": {"name": "新电途", "redis_pattern": "crawled:xdt:*"},
"3": {"name": "艾特吉易充", "redis_pattern": "crawled:aite:*"},
"4": {"name": "驿来特", "redis_pattern": "crawled:ylt:*"},
}
async def clear_vendor_data(db: Db, redis_kit: RedisKit, vendor_info: Dict):
""" """
1. 删除数据库中所有 operator='特来电' 的记录 清理特定供应商的数据库和 Redis 数据
2. 删除 Redis 中所有关于艾特吉易充的缓存信息
""" """
operator = '特来电' operator = vendor_info["name"]
pattern = vendor_info["redis_pattern"]
logger.info(f"--- 正在清理供应商: {operator} ---")
# 1. 数据库清理 # 1. 数据库清理
logger.info(f"开始清理数据库中 operator='{operator}' 的数据...")
db = Db(db_url=DB_URL)
await db.init_db()
try: try:
async with db.AsyncSessionLocal() as session: async with db.AsyncSessionLocal() as session:
async with session.begin(): async with session.begin():
@@ -52,9 +59,8 @@ async def main():
SELECT station_hash FROM t_station_profile_scd WHERE operator = :operator SELECT station_hash FROM t_station_profile_scd WHERE operator = :operator
) )
""" """
logger.info("正在清理 t_station_status_scd...")
result_status = await session.execute(text(sql_status), {"operator": operator}) result_status = await session.execute(text(sql_status), {"operator": operator})
logger.info(f"t_station_status_scd 已删除 {result_status.rowcount} 行记录。") logger.info(f"[{operator}] t_station_status_scd 已删除 {result_status.rowcount} 行。")
# 2. t_station_price_schedule_scd # 2. t_station_price_schedule_scd
sql_price = """ sql_price = """
@@ -63,42 +69,71 @@ async def main():
SELECT station_hash FROM t_station_profile_scd WHERE operator = :operator SELECT station_hash FROM t_station_profile_scd WHERE operator = :operator
) )
""" """
logger.info("正在清理 t_station_price_schedule_scd...")
result_price = await session.execute(text(sql_price), {"operator": operator}) result_price = await session.execute(text(sql_price), {"operator": operator})
logger.info(f"t_station_price_schedule_scd 已删除 {result_price.rowcount} 行记录。") logger.info(f"[{operator}] t_station_price_schedule_scd 已删除 {result_price.rowcount} 行。")
# 3. 最后删除主表 t_station_profile_scd # 3. 最后删除主表 t_station_profile_scd
sql_profile = "DELETE FROM t_station_profile_scd WHERE operator = :operator" sql_profile = "DELETE FROM t_station_profile_scd WHERE operator = :operator"
logger.info("正在清理 t_station_profile_scd...")
result_profile = await session.execute(text(sql_profile), {"operator": operator}) result_profile = await session.execute(text(sql_profile), {"operator": operator})
logger.info(f"t_station_profile_scd 已删除 {result_profile.rowcount} 行记录。") logger.info(f"[{operator}] t_station_profile_scd 已删除 {result_profile.rowcount} 行。")
logger.info("数据库记录清理完成。") logger.info(f"[{operator}] 数据库记录清理完成。")
except Exception as e: except Exception as e:
logger.error(f"数据库清理失败: {e}") logger.error(f"[{operator}] 数据库清理失败: {e}")
finally:
# 3. 资源清理
logger.info("正在关闭数据库连接...")
await db.close()
# 2. Redis 清理 # 2. Redis 清理
logger.info("开始清理 Redis 中的缓存数据...")
redis_kit = RedisKit()
# 根据特来电爬虫的约定,Redis 去重键的模式为 crawled:tld:*
pattern = "crawled:tld:*"
try: try:
keys = await redis_kit.keys(pattern) keys = await redis_kit.keys(pattern)
if keys: if keys:
logger.info(f"匹配到 {len(keys)} 个键,正在删除...") logger.info(f"[{operator}] 匹配到 {len(keys)} 个 Redis 键,正在删除...")
await redis_kit.delete(*keys) await redis_kit.delete(*keys)
logger.info("Redis 缓存清理完成。") logger.info(f"[{operator}] Redis 缓存清理完成。")
else: else:
logger.info(f"未匹配到模式为 '{pattern}' 的键。") logger.info(f"[{operator}] 未匹配到模式为 '{pattern}' 的 Redis 键。")
except Exception as e: except Exception as e:
logger.error(f"Redis 清理失败: {e}") logger.error(f"[{operator}] Redis 清理失败: {e}")
# RedisKit 目前是单例且内部使用线程池,通常不需要显式关闭,
# 但如果未来改为异步驱动,则需要在此处添加清理逻辑 async def main():
print("\n" + "="*30)
print(" 供应商数据清理工具")
print("="*30)
for key, info in VENDORS.items():
print(f"{key}. {info['name']}")
print("0. 全部清理")
print("q. 退出")
print("-" * 30)
choice = input("请输入选择的编号: ").strip().lower()
if choice == 'q':
return
selected_vendors = []
if choice == '0':
selected_vendors = list(VENDORS.values())
elif choice in VENDORS:
selected_vendors = [VENDORS[choice]]
else:
print("无效的选择,请重新运行脚本。")
return
# 初始化资源
db = Db(db_url=DB_URL)
await db.init_db()
redis_kit = RedisKit()
try:
for vendor in selected_vendors:
await clear_vendor_data(db, redis_kit, vendor)
finally:
logger.info("正在关闭数据库连接...")
await db.close()
if __name__ == "__main__": if __name__ == "__main__":
Win32Patch.patch() Win32Patch.patch()
try:
asyncio.run(main()) asyncio.run(main())
except KeyboardInterrupt:
pass
except Exception as e:
logger.error(f"程序运行异常: {e}")

Binary file not shown.