Syntaxfehler in crawler.py behoben und Admin-Benachrichtigungen für Website-Fehler implementiert
This commit is contained in:
49
crawler.py
49
crawler.py
@@ -5,6 +5,7 @@ import difflib
|
||||
import sys
|
||||
import subprocess
|
||||
import logging
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from urllib.parse import urljoin, urlparse
|
||||
from datetime import datetime
|
||||
@@ -34,6 +35,18 @@ scraper = cloudscraper.create_scraper(
|
||||
# --- DATENBANK SETUP ---
|
||||
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():
|
||||
conn = sqlite3.connect(DB_PATH, timeout=20)
|
||||
cursor = conn.cursor()
|
||||
@@ -58,19 +71,13 @@ def setup_db():
|
||||
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):
|
||||
@@ -112,17 +119,10 @@ def hole_artikel_text(url):
|
||||
try:
|
||||
antwort = scraper.get(url, timeout=10)
|
||||
soup = BeautifulSoup(antwort.text, "html.parser")
|
||||
|
||||
# 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
|
||||
|
||||
if not bereich: return None
|
||||
text = bereich.get_text(separator=" ", strip=True)
|
||||
return text[:12000]
|
||||
except Exception as e:
|
||||
@@ -143,35 +143,16 @@ def verarbeite_website(url):
|
||||
try:
|
||||
conn = sqlite3.connect(DB_PATH, timeout=20)
|
||||
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)
|
||||
if antwort.status_code != 200:
|
||||
logger.error(f"Website Fehler: {url} Status {antwort.status_code}")
|
||||
sende_admin("Crawler Fehler", f"URL {url} lieferte Status {antwort.status_code}.")
|
||||
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"]):
|
||||
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}")
|
||||
|
||||
Reference in New Issue
Block a user