101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
|
|
# coding=utf-8
|
|||
|
|
import asyncio
|
|||
|
|
import logging
|
|||
|
|
import uuid
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import time
|
|||
|
|
from PIL import Image
|
|||
|
|
|
|||
|
|
# 将项目根目录添加到 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)
|
|||
|
|
|
|||
|
|
import uiautomator2 as u2
|
|||
|
|
from Apps.AiTeJiYiChong import Kit
|
|||
|
|
from Apps.AiTeJiYiChong.Kit import take_screenshot
|
|||
|
|
from Util.RedisKit import RedisKit
|
|||
|
|
from Apps.AiTeJiYiChong.Service import AiTeJiYiChongService
|
|||
|
|
from Config.Config import TEMP_IMAGE_DIR
|
|||
|
|
from Apps.AiTeJiYiChong.Config.Setting import (
|
|||
|
|
SCROLL_DISTANCE_RATIO,
|
|||
|
|
MAX_SCROLLS, REDIS_STATION_EXPIRE,
|
|||
|
|
WAIT_AFTER_SCROLL,
|
|||
|
|
MAX_CRAWL_DISTANCE
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
logger = logging.getLogger("AiTeJiYiChongCrawler")
|
|||
|
|
|
|||
|
|
async def get_station_list(d, service, max_scrolls=MAX_SCROLLS):
|
|||
|
|
"""
|
|||
|
|
获取场站列表并处理翻页
|
|||
|
|
"""
|
|||
|
|
redis_kit = RedisKit()
|
|||
|
|
window_size = d.window_size()
|
|||
|
|
w, h = window_size[0], window_size[1]
|
|||
|
|
|
|||
|
|
device_info = d.info
|
|||
|
|
device_info['width'] = w
|
|||
|
|
device_info['height'] = h
|
|||
|
|
|
|||
|
|
logger.info(f"开始爬取列表,设备: {device_info.get('productName')} | 分辨率: {w}x{h}")
|
|||
|
|
|
|||
|
|
for i in range(max_scrolls + 1):
|
|||
|
|
logger.info(f"正在处理第 {i + 1} 页...")
|
|||
|
|
|
|||
|
|
# 1. 拍摄截图
|
|||
|
|
image_uuid = str(uuid.uuid4())
|
|||
|
|
screenshot_path = take_screenshot(d, image_uuid, save_dir=TEMP_IMAGE_DIR)
|
|||
|
|
logger.info(f"列表页截图已完成: {screenshot_path}")
|
|||
|
|
|
|||
|
|
# 2. 执行图形学分析,生成 _flag.jpg, _vl.jpg 和 .json
|
|||
|
|
logger.info("正在执行图形学切片分析...")
|
|||
|
|
json_data = Kit.crop_cards_from_image(screenshot_path)
|
|||
|
|
|
|||
|
|
# 3. 调用 VL 模型识别并保存数据
|
|||
|
|
# 这里的 service.process_station_list_vl 应该支持传入 json_data 或直接读取图片
|
|||
|
|
stations = await service.process_station_list_vl(screenshot_path, device_info=device_info)
|
|||
|
|
logger.info(f"本页识别到 {len(stations)} 个场站")
|
|||
|
|
|
|||
|
|
if not stations:
|
|||
|
|
logger.warning("本页未识别到任何场站,可能已到底或加载中")
|
|||
|
|
# 如果连续几页没数据可以考虑跳出,这里先简单处理
|
|||
|
|
|
|||
|
|
# 3. 翻页滑动
|
|||
|
|
logger.info("执行翻页滑动...")
|
|||
|
|
start_x, start_y = w // 2, int(h * 0.8)
|
|||
|
|
end_x, end_y = w // 2, int(h * (0.8 - SCROLL_DISTANCE_RATIO))
|
|||
|
|
d.swipe(start_x, start_y, end_x, end_y, duration=0.5)
|
|||
|
|
|
|||
|
|
await asyncio.sleep(WAIT_AFTER_SCROLL)
|
|||
|
|
|
|||
|
|
logger.info("达到最大翻页次数,爬取结束。")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
async def main(service=None, do_cleanup=True):
|
|||
|
|
"""
|
|||
|
|
爬虫主入口
|
|||
|
|
"""
|
|||
|
|
if do_cleanup:
|
|||
|
|
Kit.clear_temp_dir()
|
|||
|
|
|
|||
|
|
if service is None:
|
|||
|
|
service = AiTeJiYiChongService()
|
|||
|
|
await service.init_db()
|
|||
|
|
|
|||
|
|
d = u2.connect()
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
await get_station_list(d, service)
|
|||
|
|
return True
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"爬取过程中出现异常: {e}")
|
|||
|
|
return False
|
|||
|
|
finally:
|
|||
|
|
# 如果是内部初始化的 service,则在此关闭
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
asyncio.run(main())
|