Update model translations
This commit is contained in:
@@ -362,7 +362,7 @@ class EncarMapper:
|
||||
normalized = self._as_str(text)
|
||||
if not normalized:
|
||||
return normalized
|
||||
# На оригинальном сайте Encar скобок нет — убираем скобки вместе с содержимым.
|
||||
|
||||
normalized = re.sub(r"[\(\[(【][^)\])】]*[\)\])】]?", " ", normalized)
|
||||
normalized = normalized.replace("·", " ").replace("/", " ")
|
||||
normalized = re.sub(r"(?<=[A-Za-z])-클래스", " 클래스", normalized)
|
||||
@@ -370,52 +370,54 @@ class EncarMapper:
|
||||
normalized = re.sub(r"\s+", " ", normalized).strip()
|
||||
return normalized
|
||||
|
||||
def _translate_model(self, text: str) -> str:
|
||||
"""Безопасно переводит модель Encar: точные совпадения + корейские фрагменты.
|
||||
def _clean_base_model_name(self, text: str) -> str:
|
||||
model = self._as_str(text)
|
||||
if not model:
|
||||
return model
|
||||
|
||||
marketing_prefix = r"(?:The\s+All\s+New|All\s+New|The\s+New|Very\s+New|New)"
|
||||
previous = None
|
||||
while previous != model:
|
||||
previous = model
|
||||
model = re.sub(rf"^\s*{marketing_prefix}\s+", "", model, flags=re.IGNORECASE)
|
||||
|
||||
model = re.sub(r"\b\d+(?:st|nd|rd|th)\s+gen\b", " ", model, flags=re.IGNORECASE)
|
||||
model = re.sub(r"\bgen\b", " ", model, flags=re.IGNORECASE)
|
||||
model = re.sub(r"\s+", " ", model).strip(" -")
|
||||
return model
|
||||
|
||||
def _translate_model(self, text: str) -> str:
|
||||
|
||||
Старый общий replace ломал смешанные названия. Здесь английские строки
|
||||
возвращаются как есть, а короткие корейские токены заменяются только
|
||||
когда они реально присутствуют как отдельный смысловой фрагмент.
|
||||
"""
|
||||
original = self._normalize_model_text(text)
|
||||
if not original or not self._has_korean(original):
|
||||
return original
|
||||
return self._clean_base_model_name(original)
|
||||
|
||||
exact = MODEL_EXACT_TRANSLATIONS.get(original)
|
||||
if exact:
|
||||
return exact
|
||||
return self._clean_base_model_name(exact)
|
||||
|
||||
translated = original
|
||||
|
||||
# Сначала длинные точные модели и фразы — чтобы "렉с턴 스포츠 칸"
|
||||
# не превратился в "Rexton Sport 칸".
|
||||
|
||||
combined = {**MODEL_EXACT_TRANSLATIONS, **MODEL_PHRASE_TRANSLATIONS, **MODEL_TRANSLATIONS}
|
||||
for source, target in sorted(combined.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
if source in translated:
|
||||
# Заменяем только когда корейский ключ стоит как отдельный
|
||||
# смысловой фрагмент (границы — не корейские символы). Иначе
|
||||
# короткий ключ "레이" (Ray) резал бы "슈팅브레이크" → "슈팅브Ray크".
|
||||
pattern = rf"(?<![가-힣]){re.escape(source)}(?![가-힣])"
|
||||
translated = re.sub(pattern, target, translated)
|
||||
|
||||
# Потом безопасные короткие токены.
|
||||
for source, target in sorted(MODEL_TOKEN_TRANSLATIONS.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
translated = re.sub(rf"(?<![A-Za-z0-9가-힣]){re.escape(source)}(?![A-Za-z0-9가-힣])", target, translated)
|
||||
|
||||
# Типовые слитные варианты Encar: 5시리즈, S-클래스.
|
||||
translated = re.sub(r"(?<=\d)시리즈", " Series", translated)
|
||||
translated = re.sub(r"(?<=[A-Za-z])-?클래스", "-Class", translated)
|
||||
translated = re.sub(r"\b([A-Z]{1,4}) Class\b", r"\1-Class", translated)
|
||||
|
||||
# Оставшиеся непереведённые корейские фрагменты отбрасываем — как на
|
||||
# оригинальном сайте (напр. "슈팅브레이크" исчезает, не портя слово).
|
||||
translated = re.sub(r"[가-힣]+", " ", translated)
|
||||
# Чистим осиротевшую пунктуацию/скобки после удаления корейского.
|
||||
translated = re.sub(r"\(\s*\)", " ", translated)
|
||||
translated = re.sub(r"\s*-\s*(?=$|\))", "", translated)
|
||||
translated = re.sub(r"\s+([),])", r"\1", translated)
|
||||
translated = re.sub(r"\s+", " ", translated).strip(" -")
|
||||
return translated
|
||||
return self._clean_base_model_name(translated)
|
||||
|
||||
def _translate_color(self, color_raw: str) -> str:
|
||||
value = self._as_str(color_raw)
|
||||
@@ -1499,7 +1501,6 @@ class EncarScraper:
|
||||
chunks.append(tasks[i:i + BATCH_VEHICLES_CHUNK_SIZE])
|
||||
|
||||
def _fetch_chunk(chunk: list[tuple[int, str]]) -> list[tuple[int, list[ImageRecord]]]:
|
||||
"""Запрашивает фото для чанка машин одним batch-запросом."""
|
||||
ids_str = ",".join(vid for _, vid in chunk)
|
||||
path = f"/v1/readside/vehicles?vehicleIds={ids_str}&include=PHOTOS"
|
||||
for attempt in range(2):
|
||||
|
||||
Reference in New Issue
Block a user