Bump version to v1.5.3
This commit is contained in:
parent
c49864c4aa
commit
4eaef89be8
10 changed files with 3098 additions and 19 deletions
33
CHANGELOG.md
33
CHANGELOG.md
|
|
@ -1,3 +1,36 @@
|
|||
## [v1.5.3] - 2025-07-11
|
||||
|
||||
### ✨ Neue Funktionen
|
||||
|
||||
- Automatischer Volltextabruf bei zu kurzen Artikeln (< 50 Wörter)
|
||||
- Inhalte werden direkt von der Originalseite geladen (ähnlich wie bei der Bildextraktion)
|
||||
- Promobil, Camping-News und andere gängige WordPress-Seiten werden unterstützt
|
||||
|
||||
- Neue Verwaltungsseite `Feed-Verwaltung` unter `pages/01_feed_manager.py`
|
||||
- RSS-Feeds können nun über eine dedizierte Oberfläche hinzugefügt, bearbeitet und gelöscht werden
|
||||
- Anzahl verknüpfter Artikel pro Feed wird angezeigt
|
||||
- Änderungen werden protokolliert und per `st.rerun()` sofort sichtbar
|
||||
|
||||
### 🔧 Verbesserungen
|
||||
|
||||
- Feed-Filter in der Artikelübersicht zeigt jetzt die **korrekten Feed-Namen mit Artikelanzahl**
|
||||
- Beispiel: „Promobil News (12)“ statt nur „Alle (20)“
|
||||
- Basierend auf `source`-Feld im Artikelobjekt
|
||||
|
||||
- Verbesserte Logging-Ausgaben bei Feed-Aktionen (hinzufügen, ändern, löschen)
|
||||
|
||||
### 📁 Neue Dateien
|
||||
|
||||
- `utils/article_extractor.py` – Logik zum Abrufen vollständiger Artikeltexte von Originalseiten
|
||||
- `pages/01_feed_manager.py` – Eigenständige Verwaltungsseite für RSS-Feeds
|
||||
|
||||
### 🛠 Interne Änderungen
|
||||
|
||||
- `main.py` erweitert: Automatischer Fallback auf `extract_full_article()` bei zu kurzem Text
|
||||
- Logging konsolidiert und mit Feed-Aktionen ergänzt
|
||||
|
||||
|
||||
|
||||
## [v1.5.2] - 2025-07-09
|
||||
|
||||
- Fehlerbehandlung bei `CHANGELOG.md`-Doppelungen hinzugefügt
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
VERSION = "1.5.2"
|
||||
VERSION = "1.5.3"
|
||||
|
|
|
|||
30
app.py
30
app.py
|
|
@ -1,3 +1,5 @@
|
|||
# app.py (aktualisiert mit Feed-Dropdown)
|
||||
|
||||
import streamlit as st
|
||||
from datetime import datetime
|
||||
from main import (
|
||||
|
|
@ -10,6 +12,7 @@ from main import (
|
|||
)
|
||||
from utils.dalle_generator import generate_dalle_image
|
||||
import os
|
||||
from collections import Counter
|
||||
|
||||
st.set_page_config(page_title="📰 RSS Artikel Manager", layout="wide")
|
||||
st.title("📰 RSS Artikel Manager")
|
||||
|
|
@ -20,7 +23,7 @@ feeds = load_feeds()
|
|||
new_feed = st.sidebar.text_input("Neuen RSS Feed hinzufügen")
|
||||
if st.sidebar.button("Feed hinzufügen"):
|
||||
if new_feed and new_feed not in [f.get("url", f) for f in feeds]:
|
||||
feeds.append({"url": new_feed})
|
||||
feeds.append({"url": new_feed, "name": "Neuer Feed"})
|
||||
save_feeds(feeds)
|
||||
st.sidebar.success("Feed hinzugefügt")
|
||||
|
||||
|
|
@ -39,8 +42,28 @@ status_filter = st.selectbox("Status filtern", ["Alle", "New", "Rewrite", "Proce
|
|||
|
||||
all_articles = load_articles()
|
||||
articles = all_articles
|
||||
|
||||
if status_filter != "Alle":
|
||||
articles = [a for a in all_articles if a.get("status") == status_filter]
|
||||
articles = [a for a in articles if a.get("status") == status_filter]
|
||||
|
||||
# === Feed-Filter ===
|
||||
source_to_name = {f.get("url"): f.get("name", "unidentified") for f in feeds}
|
||||
source_counter = Counter([a.get("source", "unidentified") for a in articles])
|
||||
|
||||
feed_options = ["Alle ({})".format(len(articles))]
|
||||
feed_map = {}
|
||||
|
||||
for source, count in source_counter.items():
|
||||
name = source_to_name.get(source, "unidentified")
|
||||
label = f"{name} ({count})"
|
||||
feed_options.append(label)
|
||||
feed_map[label] = source
|
||||
|
||||
selected_feed_label = st.selectbox("Feed-Auswahl", feed_options)
|
||||
|
||||
if selected_feed_label != feed_options[0]: # nicht „Alle“
|
||||
selected_source = feed_map[selected_feed_label]
|
||||
articles = [a for a in articles if a.get("source", "unidentified") == selected_source]
|
||||
|
||||
# === Artikel-Tabelle ===
|
||||
if articles:
|
||||
|
|
@ -80,7 +103,6 @@ if articles:
|
|||
new_status = st.selectbox("", status_options, index=status_options.index(current_status), key=f"status_{article['id']}")
|
||||
if new_status != current_status:
|
||||
article["status"] = new_status
|
||||
# Speichern in vollständiger Artikelliste
|
||||
for idx, art in enumerate(all_articles):
|
||||
if art["id"] == article["id"]:
|
||||
all_articles[idx] = article
|
||||
|
|
@ -107,7 +129,6 @@ if articles:
|
|||
img["caption"] = caption or "Kein Bildtitel vorhanden"
|
||||
img["copyright"] = copyright or "Unbekannt"
|
||||
img["copyright_url"] = copyright_url or "#"
|
||||
# Speichern in vollständiger Artikelliste
|
||||
for idx, art in enumerate(all_articles):
|
||||
if art["id"] == article["id"]:
|
||||
all_articles[idx] = article
|
||||
|
|
@ -138,6 +159,5 @@ if articles:
|
|||
st.error("Fehler beim Erzeugen des Bildes.")
|
||||
else:
|
||||
st.info("Ein KI-generiertes Bild ist bereits vorhanden.")
|
||||
|
||||
else:
|
||||
st.info("Keine Artikel für den gewählten Status gefunden.")
|
||||
|
|
|
|||
2828
data/articles.json
2828
data/articles.json
File diff suppressed because one or more lines are too long
|
|
@ -1,3 +1,14 @@
|
|||
[
|
||||
"https://www.camping-news.de/rss/"
|
||||
{
|
||||
"url": "https://www.camping-news.de/rss/",
|
||||
"name": "Camping News"
|
||||
},
|
||||
{
|
||||
"url": "https://www.promobil.de/rss/news",
|
||||
"name": "Promobil News"
|
||||
},
|
||||
{
|
||||
"url": "https://www.promobil.de/rss/ratgeber",
|
||||
"name": "Promobil Ratgeber"
|
||||
}
|
||||
]
|
||||
|
|
@ -140,3 +140,81 @@
|
|||
2025-07-08 10:38:57,857 - INFO - 🧠 Generiere DALL·E-Bild für Prompt: Das weltweit größte Caravaning-Erlebnis
|
||||
2025-07-08 10:39:16,622 - INFO - HTTP Request: POST https://api.openai.com/v1/images/generations "HTTP/1.1 200 OK"
|
||||
2025-07-08 10:39:16,627 - INFO - ✅ Bild generiert: https://oaidalleapiprodscus.blob.core.windows.net/private/org-YimPc01cYtOXjUpCATUqDABw/user-eA31w0vmy3fOrb3G64Ygndsr/img-6d1irbwhkDKGNvLJG50pYaZK.png?st=2025-07-08T07%3A39%3A16Z&se=2025-07-08T09%3A39%3A16Z&sp=r&sv=2024-08-04&sr=b&rscd=inline&rsct=image/png&skoid=cc612491-d948-4d2e-9821-2683df3719f5&sktid=a48cca56-e6da-484e-a814-9c849652bcb3&skt=2025-07-07T20%3A35%3A26Z&ske=2025-07-08T20%3A35%3A26Z&sks=b&skv=2024-08-04&sig=DVMzSGr162NqN8830eX0tAH5Wtm5NAnTPxk2C7NQgTs%3D
|
||||
2025-07-11 08:22:15,359 - INFO - Lade Feed: https://www.camping-news.de/rss/
|
||||
2025-07-11 08:22:15,648 - INFO - 0 neue Artikel gefunden in https://www.camping-news.de/rss/
|
||||
2025-07-11 08:22:15,649 - INFO - Keine neuen Artikel gefunden.
|
||||
2025-07-11 08:29:26,863 - INFO - Lade Feed: https://www.camping-news.de/rss/
|
||||
2025-07-11 08:29:27,225 - INFO - 0 neue Artikel gefunden in https://www.camping-news.de/rss/
|
||||
2025-07-11 08:29:27,225 - INFO - Lade Feed: https://www.promobil.de/rss/news
|
||||
2025-07-11 08:29:27,464 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/termine-veranstaltungen-juni-juli/
|
||||
2025-07-11 08:29:27,618 - INFO - 13 Bilder gefunden bei https://www.promobil.de/termine-veranstaltungen-juni-juli/
|
||||
2025-07-11 08:29:27,618 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/sicherheitszubehoer-wohnmobil-schutz-einbruch-diebstahl-gase/
|
||||
2025-07-11 08:29:27,782 - INFO - 22 Bilder gefunden bei https://www.promobil.de/sicherheitszubehoer-wohnmobil-schutz-einbruch-diebstahl-gase/
|
||||
2025-07-11 08:29:27,783 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/corigon-neue-hymer-marke-sommer-2025/
|
||||
2025-07-11 08:29:27,984 - INFO - 23 Bilder gefunden bei https://www.promobil.de/corigon-neue-hymer-marke-sommer-2025/
|
||||
2025-07-11 08:29:27,985 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/sieger-frosch-campfire-der-ideen-2025/
|
||||
2025-07-11 08:29:28,132 - INFO - 21 Bilder gefunden bei https://www.promobil.de/sieger-frosch-campfire-der-ideen-2025/
|
||||
2025-07-11 08:29:28,132 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/fiat-ducato-9-gang-automatik-softwareupdate/
|
||||
2025-07-11 08:29:28,279 - INFO - 13 Bilder gefunden bei https://www.promobil.de/fiat-ducato-9-gang-automatik-softwareupdate/
|
||||
2025-07-11 08:29:28,280 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/caravaning-jahrgangs-archiv-als-pdf-download/
|
||||
2025-07-11 08:29:28,422 - INFO - 14 Bilder gefunden bei https://www.promobil.de/caravaning-jahrgangs-archiv-als-pdf-download/
|
||||
2025-07-11 08:29:28,422 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/top-10-clever-campen-videos-2024/
|
||||
2025-07-11 08:29:28,572 - INFO - 14 Bilder gefunden bei https://www.promobil.de/top-10-clever-campen-videos-2024/
|
||||
2025-07-11 08:29:28,572 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/retro-wohnmobile-2004-nuller-jahre-rueckblick-promobil/
|
||||
2025-07-11 08:29:28,761 - INFO - 25 Bilder gefunden bei https://www.promobil.de/retro-wohnmobile-2004-nuller-jahre-rueckblick-promobil/
|
||||
2025-07-11 08:29:28,761 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/gaswarner-wohnmobil-schutz-gas/
|
||||
2025-07-11 08:29:28,945 - INFO - 33 Bilder gefunden bei https://www.promobil.de/gaswarner-wohnmobil-schutz-gas/
|
||||
2025-07-11 08:29:28,946 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/versicherungen-werden-2025-teuerer-tipps-und-tricks-um-die-kosten-zu-senken/
|
||||
2025-07-11 08:29:29,104 - INFO - 13 Bilder gefunden bei https://www.promobil.de/versicherungen-werden-2025-teuerer-tipps-und-tricks-um-die-kosten-zu-senken/
|
||||
2025-07-11 08:29:29,105 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/dailycamper-trekking-mini-camper-fiat-doblo/
|
||||
2025-07-11 08:29:29,257 - INFO - 15 Bilder gefunden bei https://www.promobil.de/dailycamper-trekking-mini-camper-fiat-doblo/
|
||||
2025-07-11 08:29:29,257 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/rocket-ryzon-campingbus-von-extrem-sportler-jonas-deichmann/
|
||||
2025-07-11 08:29:29,436 - INFO - 24 Bilder gefunden bei https://www.promobil.de/rocket-ryzon-campingbus-von-extrem-sportler-jonas-deichmann/
|
||||
2025-07-11 08:29:29,436 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/e-trailer-system-kontrollboard-wohnwagen-camper/
|
||||
2025-07-11 08:29:29,593 - INFO - 16 Bilder gefunden bei https://www.promobil.de/e-trailer-system-kontrollboard-wohnwagen-camper/
|
||||
2025-07-11 08:29:29,593 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/spielorte-em-2024-red-bull-arena-leipzig/
|
||||
2025-07-11 08:29:29,786 - INFO - 19 Bilder gefunden bei https://www.promobil.de/spielorte-em-2024-red-bull-arena-leipzig/
|
||||
2025-07-11 08:29:29,786 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/can-kasim-dogan-interview-westfalia/
|
||||
2025-07-11 08:29:29,934 - INFO - 13 Bilder gefunden bei https://www.promobil.de/can-kasim-dogan-interview-westfalia/
|
||||
2025-07-11 08:29:29,934 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/promobil-leser-meinung-mobilitaet-fortbewegungsmittel-fahrrad/
|
||||
2025-07-11 08:29:30,103 - INFO - 22 Bilder gefunden bei https://www.promobil.de/promobil-leser-meinung-mobilitaet-fortbewegungsmittel-fahrrad/
|
||||
2025-07-11 08:29:30,103 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/spielorte-em-2024-frankfurt/
|
||||
2025-07-11 08:29:30,276 - INFO - 18 Bilder gefunden bei https://www.promobil.de/spielorte-em-2024-frankfurt/
|
||||
2025-07-11 08:29:30,276 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/stuttgart-em-2024-fussball-stellplaetze-wohnmobil-camping/
|
||||
2025-07-11 08:29:30,450 - INFO - 18 Bilder gefunden bei https://www.promobil.de/stuttgart-em-2024-fussball-stellplaetze-wohnmobil-camping/
|
||||
2025-07-11 08:29:30,451 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/camper-radio-radiosender-caravan-fm/
|
||||
2025-07-11 08:29:30,600 - INFO - 13 Bilder gefunden bei https://www.promobil.de/camper-radio-radiosender-caravan-fm/
|
||||
2025-07-11 08:29:30,600 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/tourismus-management-armin-brysch-interview-virtuelle-reisen/
|
||||
2025-07-11 08:29:30,750 - INFO - 13 Bilder gefunden bei https://www.promobil.de/tourismus-management-armin-brysch-interview-virtuelle-reisen/
|
||||
2025-07-11 08:29:30,750 - INFO - 20 neue Artikel gefunden in https://www.promobil.de/rss/news
|
||||
2025-07-11 08:29:30,759 - INFO - 20 neue Artikel gespeichert.
|
||||
2025-07-11 08:34:46,453 - INFO - ✍️ Umschreiben von: Schutz vor Einbruch und Diebstahl fürs Wohnmobil: Wie schütze ich mein Wohnmobil vor Diebstahl?
|
||||
2025-07-11 08:34:50,280 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:34:51,815 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:34:51,819 - INFO - ✅ Artikel umgeschrieben: Schutz vor Einbruch und Diebstahl fürs Wohnmobil: Wie schütze ich mein Wohnmobil vor Diebstahl?
|
||||
2025-07-11 08:34:51,819 - INFO - ✍️ Umschreiben von: Gaswarner im Wohnmobil: So schütze Sie sich vor unsichtbaren Gasen
|
||||
2025-07-11 08:34:57,346 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:34:59,085 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:34:59,087 - INFO - ✅ Artikel umgeschrieben: Gaswarner im Wohnmobil: So schütze Sie sich vor unsichtbaren Gasen
|
||||
2025-07-11 08:34:59,087 - INFO - ✍️ Umschreiben von: Camper-Radio Caravan.fm : Radiosender speziell für Camping-Fans
|
||||
2025-07-11 08:35:05,071 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:35:07,789 - INFO - HTTP Request: POST https://api.openai.com/v1/chat/completions "HTTP/1.1 200 OK"
|
||||
2025-07-11 08:35:07,792 - INFO - ✅ Artikel umgeschrieben: Camper-Radio Caravan.fm : Radiosender speziell für Camping-Fans
|
||||
2025-07-11 08:35:07,803 - INFO - Alle Artikel mit Status 'Rewrite' wurden verarbeitet.
|
||||
2025-07-11 08:54:52,549 - INFO - Lade Feed: https://www.camping-news.de/rss/
|
||||
2025-07-11 08:54:53,036 - INFO - 0 neue Artikel gefunden in https://www.camping-news.de/rss/
|
||||
2025-07-11 08:54:53,036 - INFO - Lade Feed: https://www.promobil.de/rss/news
|
||||
2025-07-11 08:54:53,402 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/termine-veranstaltungen-juni-juli/
|
||||
2025-07-11 08:54:53,558 - INFO - 13 Bilder gefunden bei https://www.promobil.de/termine-veranstaltungen-juni-juli/
|
||||
2025-07-11 08:54:53,731 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/sicherheitszubehoer-wohnmobil-schutz-einbruch-diebstahl-gase/
|
||||
2025-07-11 08:54:53,908 - INFO - 22 Bilder gefunden bei https://www.promobil.de/sicherheitszubehoer-wohnmobil-schutz-einbruch-diebstahl-gase/
|
||||
2025-07-11 08:54:54,076 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/fiat-ducato-9-gang-automatik-softwareupdate/
|
||||
2025-07-11 08:54:54,217 - INFO - 13 Bilder gefunden bei https://www.promobil.de/fiat-ducato-9-gang-automatik-softwareupdate/
|
||||
2025-07-11 08:54:54,376 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/versicherungen-werden-2025-teuerer-tipps-und-tricks-um-die-kosten-zu-senken/
|
||||
2025-07-11 08:54:54,537 - INFO - 13 Bilder gefunden bei https://www.promobil.de/versicherungen-werden-2025-teuerer-tipps-und-tricks-um-die-kosten-zu-senken/
|
||||
2025-07-11 08:54:54,682 - INFO - 📷 Extrahiere Bilder von https://www.promobil.de/camper-radio-radiosender-caravan-fm/
|
||||
2025-07-11 08:54:54,826 - INFO - 13 Bilder gefunden bei https://www.promobil.de/camper-radio-radiosender-caravan-fm/
|
||||
2025-07-11 08:54:54,826 - INFO - 5 neue Artikel gefunden in https://www.promobil.de/rss/news
|
||||
2025-07-11 08:54:54,834 - INFO - 5 neue Artikel gespeichert.
|
||||
2025-07-11 09:34:42,951 - INFO - ❌ Feed gelöscht: Promobil Ratgeber (https://www.promobil.de/rss/ratgeber)
|
||||
2025-07-11 09:35:05,863 - INFO - 🔗 Neuer Feed hinzugefügt: Promobil Ratgeber (https://www.promobil.de/rss/ratgeber)
|
||||
|
|
|
|||
12
main.py
12
main.py
|
|
@ -7,8 +7,9 @@ from bs4 import BeautifulSoup
|
|||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
import logging
|
||||
from utils.image_extractor import extract_images_with_metadata
|
||||
import openai
|
||||
from utils.image_extractor import extract_images_with_metadata
|
||||
from utils.article_extractor import extract_full_article
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
|
@ -75,6 +76,12 @@ def fetch_and_process_feed(feed_url, existing_ids):
|
|||
soup = BeautifulSoup(content, "html.parser")
|
||||
clean_text = soup.get_text(" ", strip=True)
|
||||
|
||||
# Automatischer Volltext-Fetch bei zu wenig Wörtern
|
||||
if len(clean_text.split()) < 50 and entry.get("link"):
|
||||
fetched_text = extract_full_article(entry["link"])
|
||||
if len(fetched_text.split()) > len(clean_text.split()):
|
||||
clean_text = fetched_text
|
||||
|
||||
images = extract_images_with_metadata(entry.link)
|
||||
|
||||
new_articles.append({
|
||||
|
|
@ -86,7 +93,8 @@ def fetch_and_process_feed(feed_url, existing_ids):
|
|||
"tags": [],
|
||||
"status": "New",
|
||||
"link": entry.get("link", ""),
|
||||
"images": images
|
||||
"images": images,
|
||||
"source": feed_url
|
||||
})
|
||||
|
||||
return new_articles
|
||||
|
|
|
|||
71
pages/01_feed_manager.py
Normal file
71
pages/01_feed_manager.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# pages/01_feed_manager.py
|
||||
|
||||
import streamlit as st
|
||||
from main import load_feeds, save_feeds, load_articles
|
||||
import logging
|
||||
|
||||
# === Logging vorbereiten ===
|
||||
log_dir = "logs"
|
||||
log_file = f"{log_dir}/rss_tool.log"
|
||||
logging.basicConfig(
|
||||
filename=log_file,
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
st.set_page_config(page_title="📡 Feed-Verwaltung")
|
||||
|
||||
st.title("📡 RSS Feed-Verwaltung")
|
||||
feeds = load_feeds()
|
||||
articles = load_articles()
|
||||
|
||||
# === Neuen Feed hinzufügen ===
|
||||
st.subheader("➕ Neuen Feed hinzufügen")
|
||||
|
||||
with st.form("add_feed_form"):
|
||||
new_url = st.text_input("Feed URL", "")
|
||||
new_name = st.text_input("Feed Name", "")
|
||||
submitted = st.form_submit_button("Feed hinzufügen")
|
||||
if submitted:
|
||||
if new_url and new_name:
|
||||
if not any(f.get("url") == new_url for f in feeds):
|
||||
feeds.append({"url": new_url, "name": new_name})
|
||||
save_feeds(feeds)
|
||||
logging.info(f"🔗 Neuer Feed hinzugefügt: {new_name} ({new_url})")
|
||||
st.success(f"Feed '{new_name}' hinzugefügt.")
|
||||
st.rerun()
|
||||
else:
|
||||
st.warning("⚠️ Dieser Feed existiert bereits.")
|
||||
else:
|
||||
st.error("❌ Bitte gib sowohl URL als auch Name ein.")
|
||||
|
||||
# === Bestehende Feeds bearbeiten ===
|
||||
st.subheader("🛠️ Vorhandene Feeds bearbeiten oder löschen")
|
||||
|
||||
for idx, feed in enumerate(feeds):
|
||||
with st.expander(f"🔗 {feed.get('name')}"):
|
||||
url = st.text_input(f"Feed-URL {idx}", value=feed.get("url"), key=f"url_{idx}")
|
||||
name = st.text_input(f"Feed-Name {idx}", value=feed.get("name"), key=f"name_{idx}")
|
||||
count = sum(1 for a in articles if a.get("source") == feed.get("url"))
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
if st.button("💾 Änderungen speichern", key=f"save_{idx}"):
|
||||
old_url, old_name = feed.get("url"), feed.get("name")
|
||||
feeds[idx]["url"] = url
|
||||
feeds[idx]["name"] = name
|
||||
save_feeds(feeds)
|
||||
logging.info(f"✏️ Feed geändert: '{old_name}' ({old_url}) → '{name}' ({url})")
|
||||
st.success("Änderungen gespeichert.")
|
||||
st.rerun()
|
||||
|
||||
with col2:
|
||||
if st.button("🗑️ Feed löschen", key=f"delete_{idx}"):
|
||||
deleted_feed = feeds.pop(idx)
|
||||
save_feeds(feeds)
|
||||
logging.info(f"❌ Feed gelöscht: {deleted_feed.get('name')} ({deleted_feed.get('url')})")
|
||||
st.warning("Feed gelöscht.")
|
||||
st.rerun()
|
||||
|
||||
st.caption(f"📰 Verknüpfte Artikel: {count}")
|
||||
27
utils/article_extractor.py
Normal file
27
utils/article_extractor.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# utils/article_extractor.py
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
def extract_full_article(url: str) -> str:
|
||||
try:
|
||||
response = requests.get(url, timeout=10)
|
||||
response.raise_for_status()
|
||||
soup = BeautifulSoup(response.text, "html.parser")
|
||||
|
||||
# Promobil & WordPress & allgemeine Fallbacks
|
||||
candidates = [
|
||||
{"tag": "div", "class_": "article__text"}, # Promobil
|
||||
{"tag": "div", "class_": "entry-content"}, # WordPress Standard
|
||||
{"tag": "article", "class_": None}, # Generisch
|
||||
]
|
||||
|
||||
for selector in candidates:
|
||||
el = soup.find(selector["tag"], class_=selector["class_"])
|
||||
if el and len(el.get_text(strip=True).split()) > 50:
|
||||
return el.get_text(" ", strip=True)
|
||||
|
||||
# Fallback: ganzer Seiteninhalt
|
||||
return soup.get_text(" ", strip=True)
|
||||
except Exception:
|
||||
return ""
|
||||
23
utils/article_utils.py
Normal file
23
utils/article_utils.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# utils/article_utils.py
|
||||
|
||||
import hashlib
|
||||
|
||||
def clean_text(text: str) -> str:
|
||||
return text.strip()
|
||||
|
||||
def generate_id(link: str) -> str:
|
||||
return hashlib.md5(link.encode("utf-8")).hexdigest()
|
||||
|
||||
def categorize_article(text: str) -> str:
|
||||
# Dummy-Kategorie
|
||||
return "Allgemein"
|
||||
|
||||
def tag_article(text: str) -> list:
|
||||
# Dummy-Tags
|
||||
return ["tag1", "tag2"]
|
||||
|
||||
def summarize_text(text: str) -> str:
|
||||
return text[:200] + "..."
|
||||
|
||||
def rewrite_text(text: str) -> str:
|
||||
return text # Platzhalter, z. B. für GPT-Rewrite später
|
||||
Loading…
Add table
Add a link
Reference in a new issue