Featured image selection picks site banners and ads instead of the article image #33
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Findings
db.media.get_first_image— the earliest-stored media row for an article. Whichever candidateMediaExtractorstored first wins.MediaExtractor.extract_media_urlsunions candidates from media-RSS,<img>tags, og:image,<picture>and bare URLs; nothing ranks them, so an image scraped from page chrome (site banner/logo) or an ad slot frequently lands first.og:imageis usually the correct featured image (Yoast derives it from the post thumbnail).Plan of attack
og:image(trafilaturaextract_metadata) and store it flagged as preferred (new column or a ranked field on media).get_first_imagebecomesget_featured_image— preferred/og image first, then media-RSS, then in-content images.Branch:
feat/issue-33-featured-image. Commits: (1):sparkles: Record og:image during full-text ingest, (2):sparkles: Rank featured image selection and suppress site banners.Agreed design (supersedes the earlier sketch)
Evidence gathered from the live db changed the approach: on onestepoffthegrid the junk (site logo SVG,
rss.png, "Supported-by" sponsor banner) recurs across articles, and — surprise — that site's ownog:imageis also a sponsor graphic. So ranking alone cannot fix it; recurrence-based suppression is the workhorse, og:image is just one ranked candidate. Separately, the ABC "multiple images" turned out to be the same asset URL with different resize query params (40 rows → 7 real images), so dedupe needs URL normalization, not perceptual hashing (dhash measured at ~20 MB for dhash+Pillow and adds false-positive risk; skipped).Selection happens at ingest; the winner is downloaded once.
entry(feed media-RSS/content, stored today) →og(trafilatura page metadata, available during full-text ingest) →content(images from entry content / stored markdown). URLs sanitized (strips the embedded-newline bug),.svgskipped.articles.featured_media_id; winner gets a media row (created if new) and the article points at it.media_downloadergains a single-image download (it currently has no production caller) so exactly the featured image is fetched locally; reader serves local file with remote fallback.Author avatars: known limitation (below og/entry in rank; caught only if feed-ubiquitous) — review after a week of use.
Branch
feat/issue-33-featured-imageCommits
:sparkles: Add featured image candidate selection service:sparkles: Choose and download the featured image at ingest:sparkles: Serve the featured image on reader cardsImplemented in PR #36 (merged as
b5980fd): featured image selection at ingest — ranked candidates (entry → og:image → content), resize-variant collapse via base-URL normalization, site-chrome suppression at ≥ 3 same-feed occurrences, SVG exclusion;articles.featured_media_id+ single-image download; reader cards prefer the featured image with legacy fallback. Hardened during review: media assignment validated, ingest log sanitization. Post-merge additions:/mediaserving resolved absolutely, article fetches send browser headers with extractor-identity retry and reject error pages.