This commit is contained in:
HuangHai
2026-01-12 08:49:17 +08:00
parent 9d57def591
commit 2787bd9df9
5 changed files with 56 additions and 56 deletions

View File

@@ -19,7 +19,7 @@ from Apps.XinDianTu.Config.Setting import (
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class XinDianTuReadImageKit: class ReadImageKit:
_client = OpenAI( _client = OpenAI(
api_key=ALY_LLM_API_KEY, api_key=ALY_LLM_API_KEY,
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1" base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
@@ -101,7 +101,7 @@ class XinDianTuReadImageKit:
@staticmethod @staticmethod
def _add_center(obj, device_info): def _add_center(obj, device_info):
return XinDianTuReadImageKit._add_click_point(obj, device_info, anchor="center") return ReadImageKit._add_click_point(obj, device_info, anchor="center")
@staticmethod @staticmethod
def _add_click_point(obj, device_info, anchor: str = "center"): def _add_click_point(obj, device_info, anchor: str = "center"):
@@ -210,7 +210,7 @@ class XinDianTuReadImageKit:
async def find_all_time_button_coordinate(image_url: str, device_info: dict = None) -> dict: async def find_all_time_button_coordinate(image_url: str, device_info: dict = None) -> dict:
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
prompt = ( prompt = (
"仅输出JSON对象(不含任何说明文字),请找到图片中带有“全部时段”字样的按钮区域(通常在价格表下方,是一个带有右箭头的文字按钮)。\n" "仅输出JSON对象(不含任何说明文字),请找到图片中带有“全部时段”字样的按钮区域(通常在价格表下方,是一个带有右箭头的文字按钮)。\n"
@@ -226,7 +226,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -247,12 +247,12 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
try: try:
data = json.loads(raw) data = json.loads(raw)
if isinstance(data, dict) and (data.get("bounds") or data.get("bounds_norm")): if isinstance(data, dict) and (data.get("bounds") or data.get("bounds_norm")):
data = XinDianTuReadImageKit._add_center(data, device_info) data = ReadImageKit._add_center(data, device_info)
# 只返回中心坐标 # 只返回中心坐标
return { return {
"uia_center_x": data.get("uia_center_x"), "uia_center_x": data.get("uia_center_x"),
@@ -268,7 +268,7 @@ class XinDianTuReadImageKit:
async def find_station_coordinate_first_page(image_url: str, station_name: str, device_info: dict = None) -> dict: async def find_station_coordinate_first_page(image_url: str, station_name: str, device_info: dict = None) -> dict:
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
prompt = ( prompt = (
"仅输出JSON对象(不含任何说明文字)。" "仅输出JSON对象(不含任何说明文字)。"
@@ -283,7 +283,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -299,14 +299,14 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
try: try:
data = json.loads(raw) data = json.loads(raw)
if isinstance(data, dict) and ( if isinstance(data, dict) and (
data.get("station_name_bounds") or data.get("station_name_bounds_norm") or data.get( data.get("station_name_bounds") or data.get("station_name_bounds_norm") or data.get(
"bounds") or data.get("bounds_norm")): "bounds") or data.get("bounds_norm")):
data = XinDianTuReadImageKit._add_click_point(data, device_info, anchor="station_text") data = ReadImageKit._add_click_point(data, device_info, anchor="station_text")
return { return {
"uia_center_x": data.get("uia_center_x"), "uia_center_x": data.get("uia_center_x"),
"uia_center_y": data.get("uia_center_y") "uia_center_y": data.get("uia_center_y")
@@ -319,12 +319,12 @@ class XinDianTuReadImageKit:
async def parse_first_level_image_url(image_url: str, device_info: dict = None) -> list: async def parse_first_level_image_url(image_url: str, device_info: dict = None) -> list:
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -337,7 +337,7 @@ class XinDianTuReadImageKit:
}, },
}, },
{"type": "text", "text": json.dumps(device_info, ensure_ascii=False)}, {"type": "text", "text": json.dumps(device_info, ensure_ascii=False)},
{"type": "text", "text": XinDianTuReadImageKit._prompt}, {"type": "text", "text": ReadImageKit._prompt},
], ],
}, },
], ],
@@ -345,18 +345,18 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
try: try:
data = json.loads(raw) data = json.loads(raw)
if isinstance(data, list): if isinstance(data, list):
# 过滤掉 None (即被 _add_click_point 排除掉的顶部项) # 过滤掉 None (即被 _add_click_point 排除掉的顶部项)
data = [XinDianTuReadImageKit._add_click_point(x, device_info, anchor="station_text") for x in data if data = [ReadImageKit._add_click_point(x, device_info, anchor="station_text") for x in data if
x.get("b_use", 1) == 1] x.get("b_use", 1) == 1]
data = [x for x in data if x is not None] data = [x for x in data if x is not None]
elif isinstance(data, dict): elif isinstance(data, dict):
if data.get("b_use", 1) == 1: if data.get("b_use", 1) == 1:
data = XinDianTuReadImageKit._add_click_point(data, device_info, anchor="station_text") data = ReadImageKit._add_click_point(data, device_info, anchor="station_text")
data = [data] if data is not None else [] data = [data] if data is not None else []
else: else:
data = [] data = []
@@ -397,7 +397,7 @@ class XinDianTuReadImageKit:
if name: if name:
idxs.append(i) idxs.append(i)
tasks.append(asyncio.create_task( tasks.append(asyncio.create_task(
XinDianTuReadImageKit.find_station_coordinate_first_page(image_url, name, device_info) ReadImageKit.find_station_coordinate_first_page(image_url, name, device_info)
)) ))
if tasks: if tasks:
results = await asyncio.gather(*tasks, return_exceptions=True) results = await asyncio.gather(*tasks, return_exceptions=True)
@@ -418,7 +418,7 @@ class XinDianTuReadImageKit:
""" """
统一入口:混合识别模式 统一入口:混合识别模式
""" """
return await XinDianTuReadImageKit.get_stations_hybrid(image_path, uploader, cdn_domain) return await ReadImageKit.get_stations_hybrid(image_path, uploader, cdn_domain)
@staticmethod @staticmethod
async def parse_vl_image(vl_image_url, json_metadata, device_info=None): async def parse_vl_image(vl_image_url, json_metadata, device_info=None):
@@ -453,7 +453,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -468,7 +468,7 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
final_stations = [] final_stations = []
try: try:
@@ -529,7 +529,7 @@ class XinDianTuReadImageKit:
混合识别模式:图形学切片 + 大模型小图 OCR 混合识别模式:图形学切片 + 大模型小图 OCR
""" """
# 1. 图形学切片 # 1. 图形学切片
segments = XinDianTuReadImageKit.get_card_segments(image_path) segments = ReadImageKit.get_card_segments(image_path)
if not segments: if not segments:
return [] return []
@@ -544,7 +544,7 @@ class XinDianTuReadImageKit:
# 记录上传后的 URL 供识别使用 # 记录上传后的 URL 供识别使用
seg["patch_url"] = patch_url seg["patch_url"] = patch_url
tasks.append(XinDianTuReadImageKit.recognize_card_text(patch_url)) tasks.append(ReadImageKit.recognize_card_text(patch_url))
# 等待所有 OCR 完成 # 等待所有 OCR 完成
results = await asyncio.gather(*tasks) results = await asyncio.gather(*tasks)
@@ -772,7 +772,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -820,7 +820,7 @@ class XinDianTuReadImageKit:
""" """
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
prompt = ( prompt = (
"分析图片中是否存在覆盖在主界面上的广告弹窗(Popup Ad)。" "分析图片中是否存在覆盖在主界面上的广告弹窗(Popup Ad)。"
@@ -834,7 +834,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME_AD, # 使用更强的视觉模型 model=VL_MODEL_NAME_AD, # 使用更强的视觉模型
messages=[ messages=[
{ {
@@ -853,7 +853,7 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
try: try:
data = json.loads(raw) data = json.loads(raw)
@@ -861,7 +861,7 @@ class XinDianTuReadImageKit:
if has_ad and data.get("close_button_bounds"): if has_ad and data.get("close_button_bounds"):
# 使用现有的辅助方法转换坐标 # 使用现有的辅助方法转换坐标
temp_obj = {"bounds": data.get("close_button_bounds")} temp_obj = {"bounds": data.get("close_button_bounds")}
XinDianTuReadImageKit._add_click_point(temp_obj, device_info) ReadImageKit._add_click_point(temp_obj, device_info)
return { return {
"has_ad": True, "has_ad": True,
"uia_center_x": temp_obj.get("uia_center_x"), "uia_center_x": temp_obj.get("uia_center_x"),
@@ -912,7 +912,7 @@ class XinDianTuReadImageKit:
""" """
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
# 视觉解析提示词:约束输出字段与格式,避免模型输出说明文字 # 视觉解析提示词:约束输出字段与格式,避免模型输出说明文字
prompt = ( prompt = (
@@ -928,7 +928,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
def _do_request(url_val): def _do_request(url_val):
return XinDianTuReadImageKit._client.chat.completions.create( return ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -957,7 +957,7 @@ class XinDianTuReadImageKit:
# 如果是媒体格式或数据检查错误 # 如果是媒体格式或数据检查错误
if 'InvalidParameter.DataInspection' in str(err_code) or 'media format' in str(e).lower(): if 'InvalidParameter.DataInspection' in str(err_code) or 'media format' in str(e).lower():
logger.warning(f"Image URL rejected ({err_code}). Attempting Base64 fallback: {image_url}") logger.warning(f"Image URL rejected ({err_code}). Attempting Base64 fallback: {image_url}")
base64_str = await XinDianTuReadImageKit._download_as_base64(image_url) base64_str = await ReadImageKit._download_as_base64(image_url)
if base64_str: if base64_str:
# 简单推断格式,默认 jpeg # 简单推断格式,默认 jpeg
ext = "jpeg" ext = "jpeg"
@@ -982,7 +982,7 @@ class XinDianTuReadImageKit:
return [] return []
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
try: try:
# 反序列化模型返回的 JSON # 反序列化模型返回的 JSON
@@ -1069,8 +1069,8 @@ class XinDianTuReadImageKit:
hourly = [] hourly = []
for r in rows: for r in rows:
# 起止时间转分钟 # 起止时间转分钟
s = XinDianTuReadImageKit._to_minutes(r.get("start")) s = ReadImageKit._to_minutes(r.get("start"))
e = XinDianTuReadImageKit._to_minutes(r.get("end")) e = ReadImageKit._to_minutes(r.get("end"))
if e <= s: if e <= s:
continue continue
cur = s cur = s
@@ -1078,8 +1078,8 @@ class XinDianTuReadImageKit:
# 下一小时边界;不超过区间终点 # 下一小时边界;不超过区间终点
nxt = min(e, ((cur // 60) + 1) * 60) nxt = min(e, ((cur // 60) + 1) * 60)
hourly.append({ hourly.append({
"start": XinDianTuReadImageKit._fmt(cur), "start": ReadImageKit._fmt(cur),
"end": XinDianTuReadImageKit._fmt(nxt), "end": ReadImageKit._fmt(nxt),
"price_kwh": r.get("price_kwh"), "price_kwh": r.get("price_kwh"),
"electric_fee_kwh": r.get("electric_fee_kwh"), "electric_fee_kwh": r.get("electric_fee_kwh"),
"service_fee_kwh": r.get("service_fee_kwh"), "service_fee_kwh": r.get("service_fee_kwh"),
@@ -1120,10 +1120,10 @@ class XinDianTuReadImageKit:
""" """
if device_info is None: if device_info is None:
logger.warning("未提供动态设备信息,使用通用回退配置。") logger.warning("未提供动态设备信息,使用通用回退配置。")
device_info = XinDianTuReadImageKit._FALLBACK_DEVICE_INFO device_info = ReadImageKit._FALLBACK_DEVICE_INFO
# 启动寻找“全部时段”按钮的任务,为后续可能的点击做准备 # 启动寻找“全部时段”按钮的任务,为后续可能的点击做准备
button_task = asyncio.create_task(XinDianTuReadImageKit.find_all_time_button_coordinate(image_url, device_info)) button_task = asyncio.create_task(ReadImageKit.find_all_time_button_coordinate(image_url, device_info))
prompt = ( prompt = (
"仅输出JSON对象(不含任何说明文字)。" "仅输出JSON对象(不含任何说明文字)。"
@@ -1139,7 +1139,7 @@ class XinDianTuReadImageKit:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
resp = await loop.run_in_executor( resp = await loop.run_in_executor(
None, None,
lambda: XinDianTuReadImageKit._client.chat.completions.create( lambda: ReadImageKit._client.chat.completions.create(
model=VL_MODEL_NAME, model=VL_MODEL_NAME,
messages=[ messages=[
{ {
@@ -1158,7 +1158,7 @@ class XinDianTuReadImageKit:
) )
content = resp.choices[0].message.content or "" content = resp.choices[0].message.content or ""
raw = XinDianTuReadImageKit._extract_json(content) raw = ReadImageKit._extract_json(content)
result = {} result = {}
try: try:
@@ -1200,14 +1200,14 @@ class XinDianTuReadImageKit:
# MD5 -> URL 的映射,用于去重 # MD5 -> URL 的映射,用于去重
md5_to_url = {} md5_to_url = {}
for u in image_urls: for u in image_urls:
m = await XinDianTuReadImageKit._fetch_md5(u) m = await ReadImageKit._fetch_md5(u)
if m and m not in md5_to_url: if m and m not in md5_to_url:
md5_to_url[m] = u md5_to_url[m] = u
unique_urls = list(md5_to_url.values()) unique_urls = list(md5_to_url.values())
# 合并时段结果 # 合并时段结果
combined = [] combined = []
for u in unique_urls: for u in unique_urls:
rows = await XinDianTuReadImageKit.parse_price_schedule(station_name, u, device_info=device_info) rows = await ReadImageKit.parse_price_schedule(station_name, u, device_info=device_info)
if rows: if rows:
combined.extend(rows) combined.extend(rows)
return combined return combined
@@ -1230,8 +1230,8 @@ class XinDianTuReadImageKit:
# 预处理:转换为分钟区间 # 预处理:转换为分钟区间
intervals = [] intervals = []
for r in rows: for r in rows:
s = XinDianTuReadImageKit._to_minutes(r.get("start")) s = ReadImageKit._to_minutes(r.get("start"))
e = XinDianTuReadImageKit._to_minutes(r.get("end")) e = ReadImageKit._to_minutes(r.get("end"))
if e <= s: if e <= s:
continue continue
s = max(0, s) s = max(0, s)
@@ -1256,8 +1256,8 @@ class XinDianTuReadImageKit:
best_overlap = overlap best_overlap = overlap
best = it best = it
result.append({ result.append({
"start": XinDianTuReadImageKit._fmt(hs), "start": ReadImageKit._fmt(hs),
"end": XinDianTuReadImageKit._fmt(he), "end": ReadImageKit._fmt(he),
"price_kwh": best["price_kwh"] if best else None, "price_kwh": best["price_kwh"] if best else None,
"electric_fee_kwh": best["electric_fee_kwh"] if best else None, "electric_fee_kwh": best["electric_fee_kwh"] if best else None,
"service_fee_kwh": best["service_fee_kwh"] if best else None, "service_fee_kwh": best["service_fee_kwh"] if best else None,
@@ -1269,7 +1269,7 @@ async def test1():
# 测试新电途第一层结构的读取 # 测试新电途第一层结构的读取
url = "https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/8fd79c68-fec6-4ca7-8d8e-fbff3c6862c8.jpg" url = "https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/8fd79c68-fec6-4ca7-8d8e-fbff3c6862c8.jpg"
print(f"Testing First Level with URL: {url}") print(f"Testing First Level with URL: {url}")
result = await XinDianTuReadImageKit.parse_first_level_image_url(url) result = await ReadImageKit.parse_first_level_image_url(url)
print("First Level Result:") print("First Level Result:")
print(json.dumps(result, ensure_ascii=False, indent=2)) print(json.dumps(result, ensure_ascii=False, indent=2))
@@ -1278,7 +1278,7 @@ async def test2(station_name: str):
# 测试新电途第二层结构的读取 # 测试新电途第二层结构的读取
url = "https://dsideal.obs.myhuaweicloud.com/HuangHai/Temp/SecondPage.jpg" url = "https://dsideal.obs.myhuaweicloud.com/HuangHai/Temp/SecondPage.jpg"
print(f"Testing address extraction from: {url}") print(f"Testing address extraction from: {url}")
result = await XinDianTuReadImageKit.parse_address(station_name, url) result = await ReadImageKit.parse_address(station_name, url)
result["station_name"] = station_name result["station_name"] = station_name
print("Address result:") print("Address result:")
print(json.dumps(result, ensure_ascii=False, indent=2)) print(json.dumps(result, ensure_ascii=False, indent=2))
@@ -1290,8 +1290,8 @@ async def test3(station_name: str):
"https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/XinDianTu/1.jpg", "https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/XinDianTu/1.jpg",
"https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/XinDianTu/2.jpg", "https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/Temp/XinDianTu/2.jpg",
] ]
rows = await XinDianTuReadImageKit.parse_price_schedule_multi(station_name, samples) rows = await ReadImageKit.parse_price_schedule_multi(station_name, samples)
hourly = XinDianTuReadImageKit.hourly_full_day(rows) hourly = ReadImageKit.hourly_full_day(rows)
print(json.dumps(hourly, ensure_ascii=False, indent=2)) print(json.dumps(hourly, ensure_ascii=False, indent=2))

View File

@@ -11,7 +11,7 @@ project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(_
if project_root not in sys.path: if project_root not in sys.path:
sys.path.append(project_root) sys.path.append(project_root)
from Apps.XinDianTu.XinDianTuReadImageKit import XinDianTuReadImageKit from Apps.XinDianTu.ReadImageKit import ReadImageKit
from DbKit.Db import Db from DbKit.Db import Db
from Config.Config import DB_URL from Config.Config import DB_URL
from Model.StationProfile import StationProfile from Model.StationProfile import StationProfile
@@ -46,7 +46,7 @@ class XinDianTuService:
""" """
基于 VL 模式处理场站列表 基于 VL 模式处理场站列表
""" """
station_list = await XinDianTuReadImageKit.parse_vl_image(vl_image_url, json_metadata, device_info=device_info) station_list = await ReadImageKit.parse_vl_image(vl_image_url, json_metadata, device_info=device_info)
if not station_list: if not station_list:
return [] return []
@@ -163,7 +163,7 @@ class XinDianTuService:
""" """
混合模式处理场站列表 (图形学切片 + OCR) 混合模式处理场站列表 (图形学切片 + OCR)
""" """
station_list = await XinDianTuReadImageKit.parse_hybrid_image(local_image_path, uploader, cdn_domain) station_list = await ReadImageKit.parse_hybrid_image(local_image_path, uploader, cdn_domain)
if not station_list: if not station_list:
return [] return []
@@ -241,7 +241,7 @@ class XinDianTuService:
return processed_stations return processed_stations
async def process_station_list(self, list_url: str, device_info: dict = None) -> list: async def process_station_list(self, list_url: str, device_info: dict = None) -> list:
station_list = await XinDianTuReadImageKit.parse_first_level_image_url(list_url, device_info=device_info) station_list = await ReadImageKit.parse_first_level_image_url(list_url, device_info=device_info)
if not station_list: if not station_list:
return [] return []
@@ -338,7 +338,7 @@ class XinDianTuService:
async def process_station_address(self, station_name: str, detail_url: str, device_info: dict = None) -> dict: async def process_station_address(self, station_name: str, detail_url: str, device_info: dict = None) -> dict:
logger.info(f"\n[Service] Processing Address for '{station_name}' from: {detail_url}") logger.info(f"\n[Service] Processing Address for '{station_name}' from: {detail_url}")
address_data = await XinDianTuReadImageKit.parse_address(station_name, detail_url, device_info=device_info) address_data = await ReadImageKit.parse_address(station_name, detail_url, device_info=device_info)
address = address_data.get("address") address = address_data.get("address")
if address: if address:
address = address.strip() address = address.strip()
@@ -493,8 +493,8 @@ class XinDianTuService:
async def process_price_schedule(self, station_name: str, schedule_urls: list, device_info: dict = None): async def process_price_schedule(self, station_name: str, schedule_urls: list, device_info: dict = None):
logger.info(f"\n[Service] Processing Price Schedule for '{station_name}'") logger.info(f"\n[Service] Processing Price Schedule for '{station_name}'")
rows = await XinDianTuReadImageKit.parse_price_schedule_multi(station_name, schedule_urls, device_info=device_info) rows = await ReadImageKit.parse_price_schedule_multi(station_name, schedule_urls, device_info=device_info)
hourly_schedule = XinDianTuReadImageKit.hourly_full_day(rows) hourly_schedule = ReadImageKit.hourly_full_day(rows)
if hourly_schedule: if hourly_schedule:
logger.info(f" - Got {len(hourly_schedule)} hourly records.") logger.info(f" - Got {len(hourly_schedule)} hourly records.")