Feed Merger

Du hast eine Idee für ein Projekt?
Antworten
Benutzeravatar
eXeler0n
User
Beiträge: 3
Registriert: Sonntag 30. Dezember 2018, 14:54

Sonntag 30. Dezember 2018, 15:52

Hallo,

mir fällt gerade kein besserer Titel ein. Ich habe mir in der Vergangenheit hin und wieder Python angeschaut und auch mal das ein oder andere Script sehr geringfügig angepasst. Zu Weihnachten hat meine Freundin mir dann ein Python Lehrbuch geschenkt, welches ich inzwischen fast komplett durchgearbeitet habe.

Jetzt kam bei mir natürlich die Frage auf, was ich mit dem neu erlangten Wissen anfangen soll. Derzeit betreibe ich für Eve Online Blogs eine Seite, welche bei den Blogs die Feeds abfragt, neue Posts erfasst und in einem neuen Feed zusammenfasst. (eveblogs.de) Das Ganze basiert derzeit auf WordPress mit einem Feed Plugin. Meiner Meinung nach ist das dafür aber Overkill.

Also möchte ich die Seite in Python neu schreiben. Dazu gehört die Abfrage der Feeds nach neuen Posts, das Speichern der gekürzten Posts in einer Datenbank und die Erstellung einer Webseite und eines RSS/Atom Feeds.

Ich nutze das gleichzeitig, um mir auch GitHub anzuschauen. Dort werde ich auch den kompletten Code veröffentlichen.
https://github.com/eXeler0n/eveblogsde

Wofür ist dieser Thread?
Ich denke ich werde auf meinem Weg immer wieder auf Probleme stoßen und spezifische Fragen haben. Diese würde ich gerne hier stellen.
Zusätzlich würde ich gerne meine Fortschritte und Erkenntnisse hier dokumentieren. Das hilft ggf. anderen Neulingen und mit etwas Glück hat ein Profi hier zwischendurch Langeweile und kann mir ggf.Tipps geben.

Wenn so ein Thread nicht erwünscht ist, dann sagt mir das einfach, dann werde ich diesen nicht weiterführen.

VG eXeler0n
Benutzeravatar
snafu
User
Beiträge: 5698
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sonntag 30. Dezember 2018, 16:04

eXeler0n hat geschrieben:
Sonntag 30. Dezember 2018, 15:52
Wenn so ein Thread nicht erwünscht ist, dann sagt mir das einfach, dann werde ich diesen nicht weiterführen.
Alles gut, für genau so etwas ist dieser Bereich schon gedacht, siehe dazu auch die anderen Threads hier im Unterforum.
Sirius3
User
Beiträge: 9077
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 30. Dezember 2018, 19:44

@eXeler0n: das Vorgehen, mit leeren Dateien anzufangen, finde ich etwas seltsam. Meist ergibt sich erst aus dem wachsenden Programm die Notwendigkeit eine Python-Sourcedatei in mehrere aufzuteilen und wo und wie stellt sich dann heraus, wenn es nötig wird. Ein Package `module` zu nennen, ist etwas verquer, und `module` ist auch ein zu generischer Name. Der Name sollte das wiederspiegeln, was Paket enthält. Bei module_xy ist das module_ unsinnig, denn dass es Module sind, ist klar, und falls daraus mal Pakete werden, ist der Name falsch.
Benutzeravatar
eXeler0n
User
Beiträge: 3
Registriert: Sonntag 30. Dezember 2018, 14:54

Sonntag 30. Dezember 2018, 21:09

Hallo zusammen,

@Sirius: Vermutlich hast du recht. Ich merke auch gerade, dass ich vermutlich eh alles etwas anders angehen werde. Feedparser hat mir eine eigene Implementierung erspart. Dafür sinkt der Lernfaktor.

Aktueller Stand:
Ich habe mich jetzt mal mit dem Fetchen von Feeds beschäftigt und herausgefunden, dass feedparser dafür wohl optimal geeignet ist.
Damit habe ich jetzt auch etwas rumgespielt und eine erste Variante der Abfrage erstellt.
Wichtig war mir, dass ich die Verwaltung der Feeds recht einfach per Dateien regeln kann. Ich habe mich für eine Datei pro Quelle entschieden. Natürlich könnte ich die Feeds auch in einer Datei untereinander schreiben, was vermutlich sogar einfacher wäre. Aber so kommt mir das übersichtlicher vor :-)
Desweiteren habe ich eine Funktion eingebaut, welche wohl nur beim ersten Produktiveinsatz interessant werden dürfte:
Ermittlung der Anzahl Einträge pro Feed und die Abfrage aller Einträge. Danach kann man das wieder auf x Einträge begrenzen.
Der Parameter cnt würde ich gerne noch aus einer config-File holen.

https://github.com/eXeler0n/eveblogsde/ ... w_posts.py

Habt ihr hier schon Verbesserungsvorschläge?

Liebe Grüße
eXeler0n
Sirius3
User
Beiträge: 9077
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 30. Dezember 2018, 22:19

@eXeler0n: so kurze Skripte postest Du am besten direkt in Deinen Beitrag, der Link zeigt zudem auf die aktuellste Version, für spätere Leser ist also nicht klar, wie das Skript zum Zeitpunkt des Posts war.
In `find_feed_url` kommt drei mal der String 'sources' vor, wenn sich da mal was ändert, muß man ihn an drei Stellen konsistent halten. Ist bei einer Funktion vielleicht noch handlebar, besser aber als Konstante am Anfang des Programms. Relative Pfade beziehen sich auf das aktuelle Verzeichnis, relative zum Skript geht über __file__. Dateien mit jeweils nur einer Zeile ist wirklich etwas uneinfach.
In `check_feeds`, vermeide nichtssagende Variablennamen, wie `d`. `cnt` und `count` sind zudem so ähnlich, dass man sich fragen muß, was denn da der Unterschied ist und nicht ständig die beiden Varianten verwechselt. Statt der while-Schleife eine for-Schleife, hier eine über `d.entries` direkt, statt über einen Index.
Statt Strings mit + zusammenzustückeln, Stringformatierung benutzen, das ist lesbarer.

Code: Alles auswählen

import os
from glob import glob
from itertools import islice
import feedparser

SOURCES = os.path.join(os.path.dirname(__file__), 'sources', '*')
MAX_FEEDS = 5 # How many items should be checked? Change to None for full fetch.

def find_feed_url():
    feed_url = []
    for filename in glob(SOURCES):
        if os.isfile(filename):
            with open(filename) as lines:
                feedurl = next(lines).rstrip()
            feed_url.append(feedurl)
    return feed_url

def check_feeds():
    for feedurl in find_feed_url():
        feeds = feedparser.parse(feedurl)
        for entry in islice(feeds.entries, MAX_FEEDS):
            postdate = '{0[0]}-{0[1]:02d}-{0[2]:02d}'.format(entry.published_parsed)
            print(d.feed.title, "|",postdate , "|", entry.title, "\n" + entry.description[:200].split('.', 1)[0], "...\n")

if __name__ == '__main__':
    check_feeds()
Benutzeravatar
eXeler0n
User
Beiträge: 3
Registriert: Sonntag 30. Dezember 2018, 14:54

Sonntag 30. Dezember 2018, 23:17

Hallo,

sieht auf jeden Fall wesentlich besser aus als mein Code. Aber ich bekomme leider eine Fehlermeldung:

Code: Alles auswählen

AttributeError: module 'os' has no attribute 'isfile'
Bin gerade überlegen, ob ich die Quellen nicht auch in eine sqlite speichere, dann habe ich weniger mit Dateien zu handeln.
Das mit dem Datum muss ich mir nochmal genauer anschauen. Ggf. brauche ich da auch noch die Uhrzeit.

Danke soweit aber schonmal.

Habs rausgefunden. Es heißt os.path.isfile - dann geht es. Und es war noch ein d. als Variable drinne :-)

Edit:
Habs mal alles angepasst.

Code: Alles auswählen

import os
from glob import glob
from itertools import islice
import feedparser

SOURCES = os.path.join(os.path.dirname(__file__), 'sources', '*')
MAX_FEEDS = 5 # How many items should be checked? Change to None for full fetch.

def find_feed_url():
    feed_url = []
    for filename in glob(SOURCES):
        if os.path.isfile(filename):
            with open(filename) as lines:
                feedurl = next(lines).rstrip()
            feed_url.append(feedurl)
    return feed_url

def check_feeds():
    for feedurl in find_feed_url():
        feeds = feedparser.parse(feedurl)
        for entry in islice(feeds.entries, MAX_FEEDS):
            postdate = '{0[0]}-{0[1]:02d}-{0[2]:02d}'.format(entry.published_parsed)
            posttime = '{0[3]:02d}:{0[4]:02d}:{0[5]:02d}'.format(entry.published_parsed)
            print(feeds.feed.title, "|",postdate , posttime, "|", entry.title, "\n" + entry.description[:200].split('.', 1)[0], "...\n")

if __name__ == '__main__':
    check_feeds()
Sirius3
User
Beiträge: 9077
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 30. Dezember 2018, 23:50

Da es sich offensichtlich um einen Zeitstempel handelt, würde das besser so aussehen:

Code: Alles auswählen

from datetime import datetime as DateTime
...
postdate = '{0:%Y-%m-%d %H:%M:%S}'.format(DateTime(*entry.published_parsed[:6]))
Antworten