import logging from urllib.parse import urlparse from services.similarity import cosine_lists logger = logging.getLogger(__name__) class Headline: display_text: str normalized_text: list[str] source_url: str domain: str published_at: object def __init__(self, display_text: str, normalized_text: list[str], source_url: str = "", published_at=None): self.display_text = display_text self.normalized_text = normalized_text self.source_url = source_url self.domain = self._extract_domain(source_url) self.published_at = published_at logger.debug( "Initialized Headline instance (display_text=%r, token_count=%d, source=%r, domain=%r, published_at=%r)", self.display_text, len(self.normalized_text), self.source_url, self.domain, self.published_at, ) @staticmethod def _extract_domain(url: str): """Return a normalized outlet domain for a source URL, or None if absent. Strips scheme, surrounding whitespace and a leading ``www.`` so that ``https://www.cnn.com/us`` and ``https://cnn.com/politics`` both resolve to ``cnn.com`` — i.e. one outlet counts once, regardless of section URL. """ if not url or not isinstance(url, str) or not url.strip(): return None host = urlparse(url.strip()).netloc.lower() if not host: return None if host.startswith("www."): host = host[4:] return host def compare_headlines(self, other_headline): if not isinstance(other_headline, Headline): logger.warning("Comparing Headline %r with incompatible object of type %s: %r", self.display_text, type(other_headline).__name__, other_headline) logger.debug("Comparing Headline %r against %r", self.display_text, getattr(other_headline, 'display_text', repr(other_headline))) try: score = cosine_lists(self.normalized_text, other_headline.normalized_text) logger.debug("Headline comparison score: %.4f between %r and %r", score, self.display_text, getattr(other_headline, 'display_text', repr(other_headline))) return score except Exception as e: logger.error("Error comparing headlines (%r vs %r): %s", self.display_text, getattr(other_headline, 'display_text', repr(other_headline)), e, exc_info=True) raise