feat: audit catalog media coverage
This commit is contained in:
@@ -39,9 +39,11 @@ def _label(node: Tag) -> str | None:
|
||||
def _kind(url: str, label: str | None, context: str) -> str:
|
||||
path = urlsplit(url).path.casefold()
|
||||
value = f"{label or ''} {context}".casefold()
|
||||
if re.search(r"/(?:fish|fishes|fische|species)/", path) or any(word in value for word in ("рыба ", "fish: ", "fisch: ")):
|
||||
if "/flags/" in path or "/themes/" in path or path.endswith(("/logo.png", "/logo.svg")):
|
||||
return "reference"
|
||||
if re.search(r"/(?:fish|fishes|fische|species)/", path) or "/media/fische/" in value or any(word in value for word in ("рыба ", "fish: ", "fisch: ")):
|
||||
return "fish"
|
||||
if re.search(r"/(?:maps?|levels?|lakes?|waterbodies)/", path) or any(word in value for word in ("карта ", "map of ", "gewässerkarte")):
|
||||
if re.search(r"/(?:maps?|levels?|lakes?|waterbodies)/", path) or "/media/levels/" in value or any(word in value for word in ("карта ", "map of ", "gewässerkarte")):
|
||||
return "waterbody"
|
||||
if re.search(r"(?:^|[/_-])(?:bait|lure|rig|rod|reel|hook|tackle|köder|rute|rolle)(?:[/_.-]|$)", path):
|
||||
return "tackle"
|
||||
@@ -63,10 +65,10 @@ def extract_media_candidates(html: str, *, source_page: str) -> list[MediaCandid
|
||||
context = " ".join(node.parent.get_text(" ", strip=True).split())[:500] if node.parent else ""
|
||||
link = node.find_parent("a", href=True)
|
||||
external_id = str(link.get("href")).rstrip("/").rsplit("/", 1)[-1] if link else None
|
||||
result.setdefault(url, MediaCandidate(source_page, url, _kind(url, label, context), label, external_id))
|
||||
result.setdefault(url, MediaCandidate(source_page, url, _kind(url, label, f"{source_page} {context}"), label, external_id))
|
||||
for match in re.finditer(r"url\((['\"]?)(https://[^)'\"]+)\1\)", html, re.I):
|
||||
url = match.group(2)
|
||||
result.setdefault(url, MediaCandidate(source_page, url, _kind(url, None, ""), None, None))
|
||||
result.setdefault(url, MediaCandidate(source_page, url, _kind(url, None, source_page), None, None))
|
||||
return list(result.values())
|
||||
|
||||
|
||||
@@ -76,7 +78,12 @@ def merge_manifest(path: Path, candidates: list[MediaCandidate]) -> dict:
|
||||
seen_at = datetime.now(timezone.utc).isoformat()
|
||||
for candidate in candidates:
|
||||
item = assets.get(candidate.asset_url, {})
|
||||
source_pages = set(item.get("source_pages", []))
|
||||
if item.get("source_page"):
|
||||
source_pages.add(item["source_page"])
|
||||
source_pages.add(candidate.source_page)
|
||||
item.update(asdict(candidate))
|
||||
item["source_pages"] = sorted(source_pages)
|
||||
item.setdefault("status", "queued")
|
||||
item.setdefault("first_seen_at", seen_at)
|
||||
item["last_seen_at"] = seen_at
|
||||
@@ -90,7 +97,8 @@ def merge_manifest(path: Path, candidates: list[MediaCandidate]) -> dict:
|
||||
def reclassify_manifest(path: Path) -> dict:
|
||||
manifest = json.loads(path.read_text(encoding="utf-8"))
|
||||
for item in manifest.get("assets", []):
|
||||
item["entity_type"] = _kind(item["asset_url"], item.get("label"), "")
|
||||
item.setdefault("source_pages", [item["source_page"]])
|
||||
item["entity_type"] = _kind(item["asset_url"], item.get("label"), item.get("source_page", ""))
|
||||
path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
return manifest
|
||||
|
||||
|
||||
Reference in New Issue
Block a user