| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- """
- 图片下载模块
- - 卡牌标准图:从 cards_master_v2 的 img_url (腾讯云COS) 下载,HTTP 直接访问
- - 交易图:从 MinIO 下载(需配置账号密码),或从本地目录读取
- """
- import os
- import hashlib
- import requests
- import cv2
- import numpy as np
- def _url_to_filename(url):
- """URL 转本地文件名(md5 防冲突)"""
- return hashlib.md5(url.encode("utf-8")).hexdigest() + ".jpg"
- def download_card_image(url, save_dir, timeout=15, retries=2):
- """
- 下载卡牌标准图(COS,HTTP 公开访问)。
- 已存在则直接返回路径(断点续传)。
- Returns: 本地路径;失败返回 None
- """
- fname = _url_to_filename(url)
- path = os.path.join(save_dir, fname)
- if os.path.exists(path) and os.path.getsize(path) > 0:
- return path
- for attempt in range(retries + 1):
- try:
- resp = requests.get(url, timeout=timeout)
- if resp.status_code == 200 and len(resp.content) > 0:
- with open(path, "wb") as f:
- f.write(resp.content)
- return path
- except Exception:
- if attempt == retries:
- return None
- return None
- def download_card_images_batch(urls, save_dir, workers=8):
- """批量下载卡牌图,返回 {url: local_path or None}"""
- from concurrent.futures import ThreadPoolExecutor, as_completed
- results = {}
- with ThreadPoolExecutor(max_workers=workers) as pool:
- futures = {pool.submit(download_card_image, url, save_dir): url for url in urls}
- for fut in as_completed(futures):
- url = futures[fut]
- try:
- results[url] = fut.result()
- except Exception:
- results[url] = None
- return results
- def load_image_rgb(path):
- """读取图片为 RGB numpy 数组"""
- if path is None or not os.path.exists(path):
- return None
- img = cv2.imread(path)
- if img is None:
- return None
- return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- # ============ 交易图获取(MinIO / 本地) ============
- def get_minio_client(minio_config):
- """创建 MinIO 客户端"""
- from minio import Minio
- return Minio(
- minio_config["endpoint"],
- access_key=minio_config["access_key"],
- secret_key=minio_config["secret_key"],
- secure=minio_config.get("secure", False),
- )
- def download_transaction_image_minio(image_uri, save_dir, minio_config, bucket=None):
- """
- 从 MinIO 下载交易图。
- image_uri 形如 'ebay102/2026-03-25-11-2/xxx.jpg'
- bucket 为 None 时,取 image_uri 第一段作为 bucket 名
- Returns: 本地路径;失败返回 None
- """
- if not minio_config.get("access_key"):
- return None # 未配置账号密码
- parts = image_uri.split("/", 1)
- if bucket is None:
- bkt, obj = parts[0], parts[1] if len(parts) > 1 else ""
- else:
- bkt, obj = bucket, image_uri
- fname = _url_to_filename(image_uri)
- path = os.path.join(save_dir, fname)
- if os.path.exists(path) and os.path.getsize(path) > 0:
- return path
- try:
- client = get_minio_client(minio_config)
- client.fget_object(bkt, obj, path)
- return path if os.path.exists(path) else None
- except Exception:
- return None
- def get_transaction_image_local(image_uri, local_root):
- """
- 从本地目录读取交易图(若图片已下载到本地)。
- local_root: 本地根目录,image_uri 拼接其后
- Returns: 本地路径或 None
- """
- path = os.path.join(local_root, image_uri)
- return path if os.path.exists(path) else None
|