'commit'
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
# coding=utf-8
|
||||
import asyncio
|
||||
import logging
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from Apps.TeLaiDian.Kit import take_screenshot, get_image_content_md5, clean_station_name, setup_logger
|
||||
import cv2
|
||||
from Apps.TeLaiDian.Kit import (
|
||||
take_screenshot, get_image_content_md5, clean_station_name,
|
||||
setup_logger, detect_price_click_point_cv, read_image, save_image
|
||||
)
|
||||
from Apps.TeLaiDian.ReadImageKit import ReadImageKit
|
||||
from Apps.TeLaiDian.Service import TeLaiDianService
|
||||
from Apps.TeLaiDian.Config.Setting import (
|
||||
@@ -120,37 +124,92 @@ class TeLaiDianCrawler(BaseCrawler):
|
||||
d.swipe_ext("up", scale=DETAIL_SCROLL_DISTANCE_RATIO)
|
||||
await asyncio.sleep(1.5)
|
||||
|
||||
# 3. 点击“价格信息”按钮 (jgxx.jpg)
|
||||
template_path = os.path.join(project_root, "Apps", "TeLaiDian", "Template", "jgxx.jpg")
|
||||
logger.info(f"尝试点击价格详情按钮: {template_path}")
|
||||
# 3. 点击“价格信息”区域 (识别橘红色价格 P0)
|
||||
price_button_screen = take_screenshot(d, f"tld_before_price_click_{int(time.time())}.jpg")
|
||||
logger.info("正在通过 CV 寻找橘红色价格区域 (P0)...")
|
||||
|
||||
click_point = detect_price_click_point_cv(price_button_screen)
|
||||
|
||||
# 调试:生成点击点标注图
|
||||
if click_point:
|
||||
debug_flag_path = price_button_screen.replace(".jpg", "_click_debug.jpg")
|
||||
img_debug = read_image(price_button_screen)
|
||||
if img_debug is not None:
|
||||
cv2.circle(img_debug, (click_point[0], click_point[1]), 20, (0, 0, 255), -1) # 红色大圆点
|
||||
cv2.line(img_debug, (click_point[0]-40, click_point[1]), (click_point[0]+40, click_point[1]), (255, 255, 255), 3)
|
||||
cv2.line(img_debug, (click_point[0], click_point[1]-40), (click_point[0], click_point[1]+40), (255, 255, 255), 3)
|
||||
save_image(debug_flag_path, img_debug)
|
||||
logger.info(f"点击点调试图已保存: {debug_flag_path}")
|
||||
|
||||
try:
|
||||
# 使用 uiautomator2 的图像识别点击
|
||||
match = d.image.match(template_path)
|
||||
if match:
|
||||
logger.info(f"找到价格按钮,坐标: {match['point']}")
|
||||
d.image.click(template_path)
|
||||
if click_point:
|
||||
logger.info(f"CV 成功定位价格区域,点击坐标: {click_point}")
|
||||
d.click(click_point[0], click_point[1])
|
||||
await asyncio.sleep(WAIT_DETAIL_PAGE_LOAD)
|
||||
else:
|
||||
logger.warning("未找到价格按钮模板,尝试备选方案:直接点击屏幕下方区域")
|
||||
# 备选方案:如果模板匹配失败,尝试点击屏幕中下方
|
||||
w, h = d.window_size()
|
||||
d.click(w // 2, int(h * 0.8))
|
||||
logger.warning("CV 未能定位价格区域,尝试模板匹配兜底...")
|
||||
template_path = os.path.join(project_root, "Apps", "TeLaiDian", "Template", "jgxx.jpg")
|
||||
match = d.image.match(template_path)
|
||||
if match:
|
||||
d.image.click(template_path)
|
||||
else:
|
||||
logger.warning("模板匹配也失败,执行坐标兜底...")
|
||||
w, h = d.window_size()
|
||||
d.click(w // 2, int(h * 0.45)) # 滑动后价格通常在屏幕中上部
|
||||
await asyncio.sleep(WAIT_DETAIL_PAGE_LOAD)
|
||||
except Exception as e:
|
||||
logger.error(f"点击价格按钮失败: {e}")
|
||||
logger.error(f"点击价格区域失败: {e}")
|
||||
finally:
|
||||
if os.path.exists(price_button_screen): os.remove(price_button_screen)
|
||||
|
||||
# 4. 截图并分析价格表
|
||||
price_screen_path = take_screenshot(d, f"tld_detail_price_{int(time.time())}.jpg")
|
||||
prices = await self.read_image_kit.analyze_detail_price(price_screen_path)
|
||||
# 4. 循环滑动抓取完整分时电价
|
||||
all_prices = []
|
||||
last_price_md5 = None
|
||||
price_page_count = 0
|
||||
max_price_pages = 3 # 分时电价通常不会超过3页
|
||||
|
||||
logger.info("开始循环滑动抓取完整分时电价...")
|
||||
|
||||
while price_page_count < max_price_pages:
|
||||
price_screen_path = take_screenshot(d, f"tld_detail_price_{int(time.time())}.jpg")
|
||||
|
||||
# 校验页面是否发生滚动变化
|
||||
curr_md5 = get_image_content_md5(price_screen_path, top_ratio=0.2, bottom_ratio=0.2)
|
||||
if curr_md5 == last_price_md5:
|
||||
logger.info("价格页面内容无变化,判定已触底")
|
||||
if os.path.exists(price_screen_path): os.remove(price_screen_path)
|
||||
break
|
||||
last_price_md5 = curr_md5
|
||||
|
||||
logger.info(f"正在分析价格详情页第 {price_page_count + 1} 页: {price_screen_path}")
|
||||
page_prices = await self.read_image_kit.analyze_detail_price(price_screen_path)
|
||||
|
||||
if page_prices:
|
||||
# 简单去重:根据时段合并
|
||||
for p in page_prices:
|
||||
if p not in all_prices:
|
||||
all_prices.append(p)
|
||||
|
||||
# 向上滑动一点点,继续抓取
|
||||
d.swipe_ext("up", scale=0.6)
|
||||
await asyncio.sleep(1.5)
|
||||
price_page_count += 1
|
||||
|
||||
# 清理临时截图
|
||||
if os.path.exists(price_screen_path): os.remove(price_screen_path)
|
||||
|
||||
# 5. 保存数据
|
||||
if prices:
|
||||
if all_prices:
|
||||
station_name_clean = clean_station_name(station_name)
|
||||
logger.info(f"场站 {station_name_clean} 提取到 {len(prices)} 条价格信息,准备保存...")
|
||||
await self.service.save_station_data(station_name_clean, address, prices)
|
||||
# 对价格按时间排序
|
||||
try:
|
||||
all_prices.sort(key=lambda x: x.get('start', '00:00'))
|
||||
except:
|
||||
pass
|
||||
logger.info(f"✅ 场站 {station_name_clean} 共提取到 {len(all_prices)} 条价格信息,准备保存...")
|
||||
await self.service.save_station_data(station_name_clean, address, all_prices)
|
||||
else:
|
||||
logger.warning(f"未能从 {price_screen_path} 提取到价格信息")
|
||||
logger.warning(f"❌ 未能提取到任何价格信息,请检查页面识别逻辑")
|
||||
|
||||
# 清理临时截图
|
||||
for p in [first_screen_path, price_screen_path]:
|
||||
|
||||
Reference in New Issue
Block a user