# cSpell:ignore momo goodsimg """ 驗證商品圖片 URL 是否正確對應到 i_code 檢查圖片 URL 中是否包含正確的商品編號 """ import os import sys import re from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # 設定路徑 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, BASE_DIR) from database.models import Product # 資料庫路徑 DB_PATH = os.path.join(BASE_DIR, 'data', 'momo_database.db') def verify_image_urls(sample_size: int = 50): """ 驗證商品圖片 URL 是否正確對應到 i_code Args: sample_size: 抽樣檢查的商品數量 """ print("🔍 驗證商品圖片 URL 是否正確對應...\n") if not os.path.exists(DB_PATH): print(f"❌ 資料庫檔案不存在: {DB_PATH}") return try: engine = create_engine(f"sqlite:///{DB_PATH}") Session = sessionmaker(bind=engine) session = Session() # 查詢有圖片的商品(隨機抽樣) products = session.query(Product).filter( Product.image_url != None, Product.image_url != '' ).limit(sample_size).all() total = len(products) print(f"📊 抽樣檢查 {total} 個有圖片的商品\n") print("=" * 80) correct_count = 0 incorrect_count = 0 unclear_count = 0 for idx, product in enumerate(products, 1): i_code = product.i_code image_url = product.image_url print(f"\n[{idx}/{total}] 商品: [{i_code}]") print(f" 名稱: {product.name[:50]}...") print(f" 圖片: {image_url}") # 檢查圖片 URL 是否包含正確的 i_code is_correct = check_image_url_match(i_code, image_url) if is_correct == True: print(f" ✅ 正確: 圖片 URL 包含商品編號") correct_count += 1 elif is_correct == False: print(f" ❌ 錯誤: 圖片 URL 不包含商品編號!") incorrect_count += 1 else: print(f" ⚠️ 無法確定: 需要人工檢查") unclear_count += 1 session.close() print("\n" + "=" * 80) print("📊 驗證結果") print("=" * 80) print(f"✅ 正確: {correct_count}/{total} ({correct_count/total*100:.1f}%)") print(f"❌ 錯誤: {incorrect_count}/{total} ({incorrect_count/total*100:.1f}%)") print(f"⚠️ 無法確定: {unclear_count}/{total} ({unclear_count/total*100:.1f}%)") if incorrect_count > 0: print(f"\n⚠️ 警告: 發現 {incorrect_count} 個商品的圖片 URL 不正確!") print("💡 建議: 執行 update_all_images.py 重新更新所有商品圖片") elif correct_count == total: print(f"\n🎉 太好了!所有抽樣商品的圖片 URL 都正確對應到 i_code") except Exception as e: print(f"❌ 驗證失敗: {e}") import traceback traceback.print_exc() def check_image_url_match(i_code: str, image_url: str) -> bool | None: """ 檢查圖片 URL 是否包含正確的 i_code Args: i_code: 商品編號 image_url: 圖片 URL Returns: True: 正確匹配 False: 不匹配 None: 無法確定 """ if not image_url: return None # MOMO 圖片 URL 的標準格式: # 1. https://og.momoshop.com.tw/{timestamp}/goodsimg/{XXXX}/{YYY}/{ZZZ}/{i_code}_L.jpg # 2. https://i{1-8}.momoshop.com.tw/{timestamp}/goodsimg/{path}/{i_code}_O.webp # 提取 URL 中的商品編號部分 # 純數字商品: 0014/548/538/14548538_L.jpg # TP 商品: TP000/0829/0000/375/TP00008290000375_O.webp if i_code.startswith('TP'): # TP 開頭的商品 # 檢查 URL 是否包含完整的 i_code if i_code in image_url: return True else: return False else: # 純數字商品 # 格式: /0014/548/538/14548538_ try: code_num = str(int(i_code)) # 去除前導零 # 檢查 URL 是否包含商品編號 if f"/{code_num}_" in image_url or f"/{code_num}." in image_url: return True # 檢查分段格式 (例如 /0014/548/538/ 對應 14548538) code_str = code_num.zfill(8) part3 = code_str[-3:] part2 = code_str[-6:-3] part1 = code_str[:-6].zfill(4) # 檢查是否包含這個路徑結構 path_pattern = f"/{part1}/{part2}/{part3}/" if path_pattern in image_url: return True return False except ValueError: # 無法轉換為數字 return None if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description='驗證商品圖片 URL') parser.add_argument('--sample-size', type=int, default=50, help='抽樣檢查的商品數量(預設: 50)') args = parser.parse_args() verify_image_urls(sample_size=args.sample_size)