feat: Add image download fallback via AutoDB AJAX API
When __carPhoto URL pattern returns 404 (e.g., timestamp-based filenames
like 1767161441_0.jpg instead of cmcar_0.jpg), fall back to fetching
actual image URLs from /common/ajax/AutoDB.html?mode=view&key={car_key}
XML response (strPhotos field).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -758,6 +758,64 @@ class CarmodooClient:
|
||||
|
||||
return result
|
||||
|
||||
async def get_car_image_urls(self, car_key: str) -> List[str]:
|
||||
"""AutoDB AJAX API를 통해 차량 이미지 URL 목록을 가져옴
|
||||
|
||||
dealerCarView.html이 사용하는 /common/ajax/AutoDB.html?mode=view&key={car_key}
|
||||
AJAX 엔드포인트를 호출하여 XML 응답의 strPhotos 필드에서 이미지 URL을 추출.
|
||||
|
||||
Args:
|
||||
car_key: 암호화된 차량 키
|
||||
|
||||
Returns:
|
||||
이미지 URL 리스트 (최대 20개)
|
||||
"""
|
||||
if not car_key:
|
||||
return []
|
||||
|
||||
if not self.is_logged_in:
|
||||
await self.login()
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=30.0, cookies=self.cookies) as client:
|
||||
url = f"{CARMODOO_BASE_URL}/common/ajax/AutoDB.html"
|
||||
params = {"mode": "view", "key": car_key}
|
||||
|
||||
response = await client.get(url, params=params, headers=self.headers)
|
||||
|
||||
if response.status_code == 200:
|
||||
try:
|
||||
xml_text = response.content.decode('euc-kr')
|
||||
except:
|
||||
xml_text = response.content.decode('utf-8', errors='replace')
|
||||
|
||||
# strPhotos 추출 (XML 태그, CDATA 포함 가능)
|
||||
photos_match = re.search(r'<strPhotos>(.*?)</strPhotos>', xml_text, re.DOTALL)
|
||||
if photos_match:
|
||||
photos_str = photos_match.group(1).strip()
|
||||
# CDATA 태그 제거
|
||||
photos_str = re.sub(r'<!\[CDATA\[', '', photos_str)
|
||||
photos_str = re.sub(r'\]\]>', '', photos_str)
|
||||
photos_str = photos_str.strip()
|
||||
if photos_str:
|
||||
urls = [u.strip() for u in photos_str.split("##") if u.strip()]
|
||||
# 상대 경로를 절대 경로로 변환
|
||||
full_urls = []
|
||||
for u in urls:
|
||||
if u.startswith('http'):
|
||||
full_urls.append(u)
|
||||
elif u.startswith('/'):
|
||||
full_urls.append(f"{CARMODOO_BASE_URL}{u}")
|
||||
else:
|
||||
full_urls.append(f"{CARMODOO_BASE_URL}/{u}")
|
||||
print(f"[Image Fallback] Found {len(full_urls)} image URLs from AutoDB for key={car_key[:20]}...")
|
||||
return full_urls
|
||||
|
||||
except Exception as e:
|
||||
print(f"Get car image URLs error: {e}")
|
||||
|
||||
return []
|
||||
|
||||
async def get_performance_check(self, car_no: str, car_key: str = "", check_num: str = "") -> dict:
|
||||
"""성능점검표 가져오기 - ck.carmodoo.com에서 조회
|
||||
|
||||
@@ -1520,6 +1578,25 @@ async def import_cars_from_carmodoo(
|
||||
if i > 0:
|
||||
break
|
||||
|
||||
# 폴백: __carPhoto에서 이미지를 못 가져온 경우 AutoDB AJAX로 실제 URL 조회
|
||||
if len(downloaded_images) == 0 and car_data.car_key:
|
||||
print(f"[Image Fallback] No images from __carPhoto for car {car.id} (car_no={car_data.car_no}), trying AutoDB...")
|
||||
fallback_urls = await carmodoo_client.get_car_image_urls(car_data.car_key)
|
||||
for i, img_url in enumerate(fallback_urls):
|
||||
local_filename = f"image_{i}.jpg"
|
||||
local_path = f"{image_base_dir}/{local_filename}"
|
||||
if await download_image(img_url, local_path):
|
||||
car_image = CarImage(
|
||||
car_id=car.id,
|
||||
url=f"/uploads/cars/{car.id}/{local_filename}",
|
||||
local_path=local_path,
|
||||
is_main=(i == 0),
|
||||
sort_order=i
|
||||
)
|
||||
db.add(car_image)
|
||||
downloaded_images.append(local_filename)
|
||||
print(f"[Image Fallback] Downloaded {len(downloaded_images)} images via AutoDB for car {car.id}")
|
||||
|
||||
# 성능점검표 가져오기 (check_num이 있으면 직접 사용)
|
||||
perf_check_result = await carmodoo_client.get_performance_check(
|
||||
car_data.car_no,
|
||||
|
||||
Reference in New Issue
Block a user