string an ki effektiver/kleiner gemacht
This commit is contained in:
61
crawler.py
61
crawler.py
@@ -57,7 +57,27 @@ def setup_db():
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
def ist_sinnvoller_text(text):
|
||||||
|
# Ignoriere Texte, die sehr kurz sind (wahrscheinlich Navigations-Links)
|
||||||
|
if len(text.strip()) < 300:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Prüfe auf zu viele generische Wörter, die auf Navigations-Seiten hindeuten
|
||||||
|
nav_keywords = ["startseite", "lokales", "aktuelles", "veranstaltungen", "kontakt", "impressum", "baustelle", "meldungen"]
|
||||||
|
text_lower = text.lower()
|
||||||
|
|
||||||
|
match_count = sum(text_lower.count(k) for k in nav_keywords)
|
||||||
|
# Wenn mehr als 5 Navigations-Begriffe vorkommen, ist es vermutlich eine Nav-Seite
|
||||||
|
if match_count > 5:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def queue_article(url, text, source_url):
|
def queue_article(url, text, source_url):
|
||||||
|
if not ist_sinnvoller_text(text):
|
||||||
|
logger.debug(f"Überspringe Müll-Text: {url}")
|
||||||
|
return
|
||||||
|
|
||||||
conn = sqlite3.connect(DB_PATH, timeout=20)
|
conn = sqlite3.connect(DB_PATH, timeout=20)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (url,))
|
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (url,))
|
||||||
@@ -91,12 +111,23 @@ def extrahiere_links(soup, basis_url):
|
|||||||
def hole_artikel_text(url):
|
def hole_artikel_text(url):
|
||||||
try:
|
try:
|
||||||
antwort = scraper.get(url, timeout=10)
|
antwort = scraper.get(url, timeout=10)
|
||||||
unter_soup = BeautifulSoup(antwort.text, "html.parser")
|
soup = BeautifulSoup(antwort.text, "html.parser")
|
||||||
bereich = unter_soup.find("main") or unter_soup.find("article") or unter_soup.body
|
|
||||||
return bereich.get_text(separator=" ", strip=True)
|
# Müll entfernen
|
||||||
|
for element in soup(["header", "footer", "nav", "script", "style", "aside"]):
|
||||||
|
element.decompose()
|
||||||
|
|
||||||
|
# Gezielter suchen
|
||||||
|
bereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content")
|
||||||
|
|
||||||
|
if not bereich:
|
||||||
|
return None
|
||||||
|
|
||||||
|
text = bereich.get_text(separator=" ", strip=True)
|
||||||
|
return text[:12000]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Fehler bei {url}: {e}")
|
logger.error(f"Fehler bei {url}: {e}")
|
||||||
return f"Fehler: {e}"
|
return None
|
||||||
|
|
||||||
def finde_link_fuer_text(text_snippet, soup, basis_url):
|
def finde_link_fuer_text(text_snippet, soup, basis_url):
|
||||||
schnipsel = text_snippet.strip().lower()
|
schnipsel = text_snippet.strip().lower()
|
||||||
@@ -115,30 +146,42 @@ def verarbeite_website(url):
|
|||||||
antwort = scraper.get(url, timeout=15)
|
antwort = scraper.get(url, timeout=15)
|
||||||
if antwort.status_code != 200: return
|
if antwort.status_code != 200: return
|
||||||
soup = BeautifulSoup(antwort.text, "html.parser")
|
soup = BeautifulSoup(antwort.text, "html.parser")
|
||||||
hauptbereich = soup.find("main") or soup.find("article") or soup.body or soup
|
|
||||||
|
# Müll entfernen
|
||||||
|
for element in soup(["header", "footer", "nav", "script", "style", "aside"]):
|
||||||
|
element.decompose()
|
||||||
|
|
||||||
|
# Gezielter suchen
|
||||||
|
hauptbereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content")
|
||||||
|
if not hauptbereich:
|
||||||
|
logger.debug(f"Überspringe Seite ohne Inhalts-Struktur: {url}")
|
||||||
|
return
|
||||||
|
|
||||||
neuer_text = hauptbereich.get_text(separator=" ", strip=True)
|
neuer_text = hauptbereich.get_text(separator=" ", strip=True)
|
||||||
cursor.execute("SELECT inhalt FROM seiten_stand WHERE url = ?", (url,))
|
cursor.execute("SELECT inhalt FROM seiten_stand WHERE url = ?", (url,))
|
||||||
zeile = cursor.fetchone()
|
zeile = cursor.fetchone()
|
||||||
alter_text = zeile[0] if zeile else ""
|
alter_text = zeile[0] if zeile else ""
|
||||||
|
|
||||||
aktuelle_links = extrahiere_links(hauptbereich, url)
|
aktuelle_links = extrahiere_links(soup, url)
|
||||||
for link in aktuelle_links:
|
for link in aktuelle_links:
|
||||||
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (link,))
|
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (link,))
|
||||||
if cursor.fetchone() is None:
|
if cursor.fetchone() is None:
|
||||||
logger.info(f"Neu: {link}")
|
logger.info(f"Neu: {link}")
|
||||||
artikel_inhalt = hole_artikel_text(link)
|
artikel_inhalt = hole_artikel_text(link)
|
||||||
queue_article(link, artikel_inhalt, url)
|
if artikel_inhalt:
|
||||||
|
queue_article(link, artikel_inhalt, url)
|
||||||
|
|
||||||
if alter_text != neuer_text:
|
if alter_text != neuer_text:
|
||||||
diff = [z[2:] for z in difflib.ndiff(alter_text.splitlines(), neuer_text.splitlines()) if z.startswith("+ ") and len(z[2:].strip()) > 30]
|
diff = [z[2:] for z in difflib.ndiff(alter_text.splitlines(), neuer_text.splitlines()) if z.startswith("+ ") and len(z[2:].strip()) > 30]
|
||||||
for line in diff:
|
for line in diff:
|
||||||
passender_link = finde_link_fuer_text(line[:40], hauptbereich, url)
|
passender_link = finde_link_fuer_text(line[:40], soup, url)
|
||||||
target_url = passender_link if passender_link else url
|
target_url = passender_link if passender_link else url
|
||||||
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (target_url,))
|
cursor.execute("SELECT 1 FROM artikel WHERE artikel_url = ?", (target_url,))
|
||||||
if cursor.fetchone() is None:
|
if cursor.fetchone() is None:
|
||||||
logger.info(f"Änderung: {target_url}")
|
logger.info(f"Änderung: {target_url}")
|
||||||
text_zu_analysieren = hole_artikel_text(passender_link) if passender_link else line
|
text_zu_analysieren = hole_artikel_text(passender_link) if passender_link else line
|
||||||
queue_article(target_url, text_zu_analysieren, url)
|
if text_zu_analysieren:
|
||||||
|
queue_article(target_url, text_zu_analysieren, url)
|
||||||
|
|
||||||
cursor.execute("INSERT OR REPLACE INTO seiten_stand (url, inhalt, zeit) VALUES (?, ?, ?)", (url, neuer_text, str(datetime.now())))
|
cursor.execute("INSERT OR REPLACE INTO seiten_stand (url, inhalt, zeit) VALUES (?, ?, ?)", (url, neuer_text, str(datetime.now())))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|||||||
Reference in New Issue
Block a user