Spaces:
Sleeping
Sleeping
File size: 1,677 Bytes
ebab0e2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import re
from typing import Optional, Tuple
import trafilatura
from bs4 import BeautifulSoup
def extract_content(html: str, url: Optional[str] = None) -> Tuple[str, str]:
"""Extract a title and the main readable text from a page's HTML.
Uses trafilatura (a readability-style extractor) as the primary
strategy, since it identifies and drops boilerplate (nav, ads, social
widgets, footers) far more reliably than a class/id substring match.
Falls back to a plain BeautifulSoup text dump for pages trafilatura
can't parse at all (e.g. near-empty pages), so the API still returns
something rather than an error.
"""
document = trafilatura.bare_extraction(
html,
url=url,
include_comments=False,
include_tables=False,
favor_recall=True,
with_metadata=True,
)
text = (document.text or "").strip() if document else ""
title = (document.title or "").strip() if document else ""
if not text:
title, text = _fallback_extract(html)
if not title:
title = _title_from_html(html)
return title or "No title found", text
def _title_from_html(html: str) -> str:
soup = BeautifulSoup(html, "lxml")
if soup.title and soup.title.string:
return soup.title.string.strip()
return ""
def _fallback_extract(html: str) -> Tuple[str, str]:
soup = BeautifulSoup(html, "lxml")
title = _title_from_html(html)
for tag in soup(["script", "style", "iframe", "noscript", "meta", "link", "svg"]):
tag.decompose()
text = soup.get_text(separator="\n", strip=True)
text = re.sub(r"\n{3,}", "\n\n", text)
return title, text
|