graph
This commit is contained in:
@@ -167,6 +167,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
brand = next((entity for entity in entities if entity.entity_type == "Brand"), None)
|
||||
for card in product_cards:
|
||||
if brand:
|
||||
evidence = brand_evidence_for_product(brand, str(card["name"]), page_text) or brand.evidence_text or brand.name
|
||||
claims.append(
|
||||
ExtractedClaim(
|
||||
str(card["name"]),
|
||||
@@ -174,7 +175,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
"hasBrand",
|
||||
brand.name,
|
||||
"Brand",
|
||||
evidence_text=brand.evidence_text or brand.name,
|
||||
evidence_text=evidence,
|
||||
confidence=0.72,
|
||||
confidence_reason="site brand inferred from listing page",
|
||||
)
|
||||
@@ -199,6 +200,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
claims: list[ExtractedClaim] = []
|
||||
brand = next((entity for entity in entities if entity.entity_type == "Brand"), None)
|
||||
if brand:
|
||||
evidence = brand_evidence_for_product(brand, perfume.name, page_text) or brand.evidence_text or brand.name
|
||||
claims.append(
|
||||
ExtractedClaim(
|
||||
perfume.name,
|
||||
@@ -206,7 +208,7 @@ class PerfumeRuleBasedExtractor(GenericRuleBasedExtractor):
|
||||
"hasBrand",
|
||||
brand.name,
|
||||
"Brand",
|
||||
evidence_text=brand.evidence_text or brand.name,
|
||||
evidence_text=evidence,
|
||||
confidence=0.78,
|
||||
confidence_reason="brand pattern matched",
|
||||
)
|
||||
@@ -273,14 +275,16 @@ def extract_brand(page_text: str, product_name: str) -> str | None:
|
||||
for pattern in patterns:
|
||||
match = re.search(pattern, page_text, flags=re.IGNORECASE)
|
||||
if match:
|
||||
return cleanup_value(match.group("brand"))
|
||||
inferred = infer_site_brand(page_text)
|
||||
brand = valid_brand(cleanup_value(match.group("brand")))
|
||||
if brand:
|
||||
return brand
|
||||
inferred = infer_site_brand(page_text, product_name)
|
||||
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) and product_line_score(candidate) <= 0:
|
||||
if valid_brand(candidate) and len(candidate) <= 80 and not looks_like_navigation(candidate) and product_line_score(candidate) <= 0:
|
||||
return candidate
|
||||
return None
|
||||
|
||||
@@ -301,6 +305,19 @@ def product_line_score(value: str) -> int:
|
||||
return score
|
||||
|
||||
|
||||
def looks_like_price(value: str | None) -> bool:
|
||||
if not value:
|
||||
return False
|
||||
clean = cleanup_value(str(value))
|
||||
return bool(
|
||||
re.fullmatch(
|
||||
r"(?:[$€£]\s*)?\d{1,3}(?:,\d{3})*(?:\.\d+)?\s*(?:원|KRW|USD|EUR|JPY|\$|€|£)?",
|
||||
clean,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def looks_like_metric_or_price(value: str) -> bool:
|
||||
clean = value.replace(",", "").strip()
|
||||
if re.fullmatch(r"\d+(?:\.\d+)?", clean):
|
||||
@@ -385,7 +402,10 @@ def dedupe_product_cards(cards: list[dict[str, object]]) -> list[dict[str, objec
|
||||
return result
|
||||
|
||||
|
||||
def infer_site_brand(page_text: str) -> str | None:
|
||||
def infer_site_brand(page_text: str, product_name: str = "") -> str | None:
|
||||
brand_context = f"{product_name}\n{page_text[:1200]}".lower()
|
||||
if "forment" in brand_context or "포맨트" in brand_context:
|
||||
return "FORMENT"
|
||||
if "912 공식 홈페이지" in page_text or "912" in page_text[:500]:
|
||||
return "912"
|
||||
return None
|
||||
@@ -394,9 +414,19 @@ def infer_site_brand(page_text: str) -> str | None:
|
||||
def valid_brand(value: str | None) -> str | None:
|
||||
if not value or is_template_placeholder(value):
|
||||
return None
|
||||
if looks_like_price(value) or looks_like_metric_or_price(value):
|
||||
return None
|
||||
return value
|
||||
|
||||
|
||||
def brand_evidence_for_product(brand: ExtractedEntity, product_name: str, page_text: str) -> str | None:
|
||||
if brand.name == "FORMENT" and "포맨트" in product_name:
|
||||
return product_name
|
||||
if brand.name.lower() in page_text.lower():
|
||||
return brand.name
|
||||
return None
|
||||
|
||||
|
||||
def extract_field_values(field: str, page_text: str) -> list[tuple[str, str]]:
|
||||
if field in NOTE_LABELS:
|
||||
return extract_labeled_values(page_text, NOTE_LABELS[field])
|
||||
|
||||
Reference in New Issue
Block a user