Syntaxfehler in crawler.py behoben und Admin-Benachrichtigungen für Website-Fehler implementiert

This commit is contained in:
2026-04-04 15:43:13 +02:00
parent ec74a66862
commit d4f76692db

View File

@@ -5,6 +5,7 @@ import difflib
import sys import sys
import subprocess import subprocess
import logging import logging
import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse from urllib.parse import urljoin, urlparse
from datetime import datetime from datetime import datetime
@@ -34,6 +35,18 @@ scraper = cloudscraper.create_scraper(
# --- DATENBANK SETUP --- # --- DATENBANK SETUP ---
DB_PATH = os.path.join(BASE_DIR, "polit_scraper.db") DB_PATH = os.path.join(BASE_DIR, "polit_scraper.db")
def sende_admin(titel, nachricht):
admin_url = f"{os.getenv('NTFY_BASE')}/polit-scraper-admin"
try:
requests.post(
admin_url,
data=nachricht.encode("utf-8"),
headers={"Title": titel.encode("utf-8"), "Priority": "4"},
auth=(os.getenv("ADMIN_USER"), os.getenv("ADMIN_PW")),
timeout=5
)
except: pass
def setup_db(): def setup_db():
conn = sqlite3.connect(DB_PATH, timeout=20) conn = sqlite3.connect(DB_PATH, timeout=20)
cursor = conn.cursor() cursor = conn.cursor()
@@ -58,19 +71,13 @@ def setup_db():
conn.close() conn.close()
def ist_sinnvoller_text(text): def ist_sinnvoller_text(text):
# Ignoriere Texte, die sehr kurz sind (wahrscheinlich Navigations-Links)
if len(text.strip()) < 300: if len(text.strip()) < 300:
return False 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"] nav_keywords = ["startseite", "lokales", "aktuelles", "veranstaltungen", "kontakt", "impressum", "baustelle", "meldungen"]
text_lower = text.lower() text_lower = text.lower()
match_count = sum(text_lower.count(k) for k in nav_keywords) 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: if match_count > 5:
return False return False
return True return True
def queue_article(url, text, source_url): def queue_article(url, text, source_url):
@@ -112,17 +119,10 @@ def hole_artikel_text(url):
try: try:
antwort = scraper.get(url, timeout=10) antwort = scraper.get(url, timeout=10)
soup = BeautifulSoup(antwort.text, "html.parser") soup = BeautifulSoup(antwort.text, "html.parser")
# Müll entfernen
for element in soup(["header", "footer", "nav", "script", "style", "aside"]): for element in soup(["header", "footer", "nav", "script", "style", "aside"]):
element.decompose() element.decompose()
# Gezielter suchen
bereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content") bereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content")
if not bereich: return None
if not bereich:
return None
text = bereich.get_text(separator=" ", strip=True) text = bereich.get_text(separator=" ", strip=True)
return text[:12000] return text[:12000]
except Exception as e: except Exception as e:
@@ -143,35 +143,16 @@ def verarbeite_website(url):
try: try:
conn = sqlite3.connect(DB_PATH, timeout=20) conn = sqlite3.connect(DB_PATH, timeout=20)
cursor = conn.cursor() cursor = conn.cursor()
import requests
from urllib.parse import urljoin, urlparse
# ...
def sende_admin(titel, nachricht):
admin_url = f"{os.getenv('NTFY_BASE')}/polit-scraper-admin"
try:
requests.post(
admin_url,
data=nachricht.encode("utf-8"),
headers={"Title": titel.encode("utf-8"), "Priority": "4"},
auth=(os.getenv("ADMIN_USER"), os.getenv("ADMIN_PW")),
timeout=5
)
except: pass
# ... in verarbeite_website ...
antwort = scraper.get(url, timeout=15) antwort = scraper.get(url, timeout=15)
if antwort.status_code != 200: if antwort.status_code != 200:
logger.error(f"Website Fehler: {url} Status {antwort.status_code}") logger.error(f"Website Fehler: {url} Status {antwort.status_code}")
sende_admin("Crawler Fehler", f"URL {url} lieferte Status {antwort.status_code}.") sende_admin("Crawler Fehler", f"URL {url} lieferte Status {antwort.status_code}.")
return return
soup = BeautifulSoup(antwort.text, "html.parser")
# Müll entfernen soup = BeautifulSoup(antwort.text, "html.parser")
for element in soup(["header", "footer", "nav", "script", "style", "aside"]): for element in soup(["header", "footer", "nav", "script", "style", "aside"]):
element.decompose() element.decompose()
# Gezielter suchen
hauptbereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content") hauptbereich = soup.find("main") or soup.find("article") or soup.find("div", class_="content")
if not hauptbereich: if not hauptbereich:
logger.debug(f"Überspringe Seite ohne Inhalts-Struktur: {url}") logger.debug(f"Überspringe Seite ohne Inhalts-Struktur: {url}")