105 lines
4.2 KiB
Python
105 lines
4.2 KiB
Python
|
|
# coding=utf-8
|
|||
|
|
import asyncio
|
|||
|
|
import logging
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
|
|||
|
|
# 将项目根目录添加到 sys.path
|
|||
|
|
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|||
|
|
if project_root not in sys.path:
|
|||
|
|
sys.path.append(project_root)
|
|||
|
|
|
|||
|
|
from Apps.XinDianTu.Service import XinDianTuService
|
|||
|
|
from Apps.XinDianTu import Opener
|
|||
|
|
from Apps.XinDianTu import Crawler
|
|||
|
|
from Apps.XinDianTu import Coord as Y4_Coord
|
|||
|
|
from Apps.XinDianTu import GetCookie as T2_GetAmapCookie
|
|||
|
|
|
|||
|
|
# 配置日志
|
|||
|
|
logging.basicConfig(
|
|||
|
|
level=logging.INFO,
|
|||
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|||
|
|
)
|
|||
|
|
logger = logging.getLogger("FullProcess")
|
|||
|
|
|
|||
|
|
async def main():
|
|||
|
|
logger.info("=== 开始全流程任务: 打开小程序 -> 爬取数据 ===")
|
|||
|
|
|
|||
|
|
# 步骤 0: 初始化基础服务 (DB等)
|
|||
|
|
# 用户要求:程序启动时就完成初始化
|
|||
|
|
logger.info(">>> 步骤 0: 初始化基础服务 (数据库连接)...")
|
|||
|
|
service = XinDianTuService()
|
|||
|
|
await service.init_db()
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 步骤 1: 打开新电途小程序
|
|||
|
|
logger.info(">>> 步骤 1: 启动新电途小程序...")
|
|||
|
|
try:
|
|||
|
|
# 调用 Y2 的 open_mini_program 函数
|
|||
|
|
success = await Opener.open_mini_program()
|
|||
|
|
if not success:
|
|||
|
|
logger.error("❌ 无法成功打开新电途小程序,任务终止。")
|
|||
|
|
return
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ 步骤 1 执行异常: {e}")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
logger.info("✅ 小程序启动成功,等待 5 秒确保界面稳定...")
|
|||
|
|
await asyncio.sleep(5)
|
|||
|
|
|
|||
|
|
# 步骤 2: 执行爬取任务
|
|||
|
|
logger.info(">>> 步骤 2: 开始执行场站爬取任务...")
|
|||
|
|
try:
|
|||
|
|
# 调用 Y3 的 main 函数,传入已初始化的 service
|
|||
|
|
# 传入 do_cleanup=False,因为已在步骤 0 完成清理
|
|||
|
|
success = await Crawler.main(service=service, do_cleanup=False)
|
|||
|
|
if not success:
|
|||
|
|
logger.error("❌ 步骤 2 爬取任务失败,终止后续步骤。")
|
|||
|
|
return
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ 步骤 2 执行异常: {e}")
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 步骤 3: 补全坐标 (调用 Y4_Coord)
|
|||
|
|
logger.info(">>> 步骤 3: 启动高德地图坐标回填任务...")
|
|||
|
|
try:
|
|||
|
|
# 首次尝试,开启 Cookie 检查
|
|||
|
|
await Y4_Coord.main(check_cookie_first=True)
|
|||
|
|
except Y4_Coord.CookieInvalidError:
|
|||
|
|
logger.warning("⚠️ 检测到高德地图 Cookie 失效或缺失。")
|
|||
|
|
logger.info(">>> 正在启动 Cookie 获取工具 (T2)...")
|
|||
|
|
logger.info("请在弹出的浏览器窗口中完成登录,然后在控制台按回车确认。")
|
|||
|
|
|
|||
|
|
# 调用同步的 T2 工具
|
|||
|
|
# 由于 T2 包含 input() 阻塞,且这是客户端脚本,直接调用即可
|
|||
|
|
try:
|
|||
|
|
# 传入 force=True 跳过“文件已存在”的询问,因为我们确定它无效
|
|||
|
|
# run_in_executor 用于避免完全阻塞事件循环(虽然在这里影响不大)
|
|||
|
|
loop = asyncio.get_event_loop()
|
|||
|
|
success = await loop.run_in_executor(None, T2_GetAmapCookie.run_login_tool, True)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
logger.info("✅ Cookie 更新成功,正在重新启动坐标回填任务...")
|
|||
|
|
# 再次尝试执行,这次可以跳过检查(刚获取完)或者继续检查
|
|||
|
|
await Y4_Coord.main(check_cookie_first=False)
|
|||
|
|
else:
|
|||
|
|
logger.error("❌ Cookie 获取失败或用户取消,跳过坐标回填步骤。")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ 调用 T2 工具失败: {e}")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"❌ 步骤 3 执行异常: {e}")
|
|||
|
|
|
|||
|
|
finally:
|
|||
|
|
# 确保数据库连接关闭
|
|||
|
|
if service:
|
|||
|
|
await service.close_db()
|
|||
|
|
logger.info("=== 全流程任务结束 ===")
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
try:
|
|||
|
|
asyncio.run(main())
|
|||
|
|
except KeyboardInterrupt:
|
|||
|
|
logger.info("程序被用户中断.")
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.exception(f"主程序崩溃: {e}")
|