ontology
This commit is contained in:
@@ -118,7 +118,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
price = find_price(page_text)
|
||||
if price:
|
||||
attrs["price"] = {k: v for k, v in price.items() if k != "evidence"}
|
||||
entities = [ExtractedEntity("Perfume", product_name, attrs, confidence=0.68)]
|
||||
entities = [ExtractedEntity("Perfume", product_name, attrs, confidence=0.74)]
|
||||
if brand:
|
||||
entities.append(ExtractedEntity("Brand", brand, confidence=0.62))
|
||||
for field, entity_type in [
|
||||
@@ -187,7 +187,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
"hasPrice",
|
||||
object_value=card["price"],
|
||||
evidence_text=str(card.get("evidence") or card["name"]),
|
||||
confidence=0.76,
|
||||
confidence=0.84,
|
||||
confidence_reason="Korean product listing price pattern matched",
|
||||
)
|
||||
)
|
||||
@@ -236,7 +236,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
"hasPrice",
|
||||
object_value={k: v for k, v in price.items() if k != "evidence"},
|
||||
evidence_text=price["evidence"],
|
||||
confidence=0.7,
|
||||
confidence=0.86,
|
||||
confidence_reason="price pattern matched",
|
||||
)
|
||||
)
|
||||
@@ -249,10 +249,19 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
|
||||
|
||||
def extract_product_name(page_text: str) -> str:
|
||||
for line in page_text.splitlines()[:8]:
|
||||
candidates: list[tuple[int, str]] = []
|
||||
for line in page_text.splitlines()[:12]:
|
||||
clean = line.strip()
|
||||
if clean and not looks_like_navigation(clean) and not is_template_placeholder(clean):
|
||||
return clean[:240]
|
||||
if not clean or looks_like_navigation(clean) or is_template_placeholder(clean):
|
||||
continue
|
||||
if looks_like_metric_or_price(clean):
|
||||
continue
|
||||
candidates.append((product_line_score(clean), clean[:240]))
|
||||
strong = [candidate for candidate in candidates if candidate[0] > 0]
|
||||
if strong:
|
||||
return max(strong, key=lambda item: item[0])[1]
|
||||
if candidates:
|
||||
return candidates[0][1]
|
||||
return first_non_empty_line(page_text) or "Unknown Perfume"
|
||||
|
||||
|
||||
@@ -265,14 +274,40 @@ def extract_brand(page_text: str, product_name: str) -> str | None:
|
||||
match = re.search(pattern, page_text, flags=re.IGNORECASE)
|
||||
if match:
|
||||
return cleanup_value(match.group("brand"))
|
||||
inferred = infer_site_brand(page_text)
|
||||
if inferred:
|
||||
return inferred
|
||||
lines = [line.strip() for line in page_text.splitlines() if line.strip()]
|
||||
if len(lines) >= 2 and lines[1].lower() not in product_name.lower():
|
||||
candidate = cleanup_value(lines[1])
|
||||
if len(candidate) <= 80 and not looks_like_navigation(candidate):
|
||||
if len(candidate) <= 80 and not looks_like_navigation(candidate) and product_line_score(candidate) <= 0:
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
def product_line_score(value: str) -> int:
|
||||
lower = value.lower()
|
||||
score = 0
|
||||
if re.search(r"\d+\s*(?:ml|g|개입)", lower):
|
||||
score += 4
|
||||
if any(keyword in value for keyword in ["향수", "디퓨저", "스프레이", "핸드크림", "미스트", "샤쉐", "퍼퓸"]):
|
||||
score += 3
|
||||
if value.startswith("[") or any(keyword in value for keyword in ["기획", "추가할인", "모음"]):
|
||||
score += 2
|
||||
if "912" in value:
|
||||
score += 2
|
||||
if "시작" in value and not re.search(r"\d+\s*(?:ml|g|개입)", lower):
|
||||
score -= 4
|
||||
return score
|
||||
|
||||
|
||||
def looks_like_metric_or_price(value: str) -> bool:
|
||||
clean = value.replace(",", "").strip()
|
||||
if re.fullmatch(r"\d+(?:\.\d+)?", clean):
|
||||
return True
|
||||
return bool(re.fullmatch(r"\d+(?:\.\d+)?\s*(?:원|krw|usd)?", clean, flags=re.IGNORECASE))
|
||||
|
||||
|
||||
def extract_product_cards(page_text: str) -> list[dict[str, object]]:
|
||||
lines = [line.strip() for line in page_text.splitlines() if line.strip()]
|
||||
cards: list[dict[str, object]] = []
|
||||
|
||||
Reference in New Issue
Block a user