Navigation
MailWebsiteChanges ist ein Python-Programm, welches Seiten abruft und anhand eines Regelwerks aus XPath-Angaben, CSS-Selektoren und Regulären Ausdrücken erkennt, ob sich die Seite seit dem letzten Abruf verändert hat. Bei einer Änderung kann es entweder eine Email zustellen, einen Newsfeed erstellen oder beides. Es wird nicht nur angegeben, dass sich etwas geändert hat sondern auch der neue Teil wird als Text zur Verfügung gestellt.
Solch ein Programm wird z. B. benötigt, wenn es auf einer Webseite keinen Newsfeed gibt, man aber trotzdem wissen möchte, wenn sich etwas getan hat, ohne jeden Tag diese Seite zu besuchen.
Den Code gibt es auf GitHub. Als Lizenz wird die GPLv2 verwendet.
Das Programm soll dem Benutzer www-data zugehörig sein und im Verzeichnis /var/www/checker wohnen. Es schreibt seinen Newsfeed nach /var/www/ttrss/htdocs/checkerfeed.xml, wo es dann von Tiny Tiny RSS abgerufen werden kann. Emails sollen nicht verschickt werden.
Als root:
apt-get install python3-lxml
mkdir /var/www/checker cd /var/www/checker
wget https://github.com/Debianguru/MailWebsiteChanges/archive/master.zip unzip -j master.zip
Nun geben wir dem Benutzer www-data noch die Zugriffsrechte für sein neues Spielzeug:
chown -R www-data: /var/www/checker
cp config_template.py config.py $EDITOR config.py
Die Variable sites
muss man nun nach seinen Bedürfnissen einstellen, die bei mir verwendete Datei findet man weiter unten…
–dry-run
utf-8
, bei Deutsch-sprachigen Seiten auch mal ISO-8859-9
.Die Dokumentation aller Werte gibt es hier.
Angenommen, man möchte die Download-Seite von Tine20 überwachen, diese liegt unter https://www.tine20.org/download/download.html.
Dann verwendet man z. B. den folgenden Eintrag in der Konfiguration:
sites = [ {'shortname': 'Tine 20 - Downloads', 'uri': 'https://www.tine20.org/download/download.html', 'type': 'html', 'titlexpath': "//div[contains(@class,'downloadArea')]//td[contains(@class, 'tableheader')]", 'contentxpath': "//div[contains(@class,'downloadArea')]//table[contains(@class, 'contenttable')]", 'encoding': 'utf-8'} ]
Ob die XPath-Angaben oder die Regulären Ausdrücken für eine Web-Seite funktionieren, sollte man mit einem Trockenlauf überprüfen:
python3 MailWebsiteChanges.py --dry-run="Tine 20 - Downloads" --config=config
Als Ausgabe erscheint der für die Angaben passende Teil der Web-Seite:
{'titles': ['Stable: Kristina (2013.03.8)', 'Beta: Collin (2013.10.1~beta2)'], 'warning': ... ... gekürzt ... </tbody>\n</table>\n']}
Das sieht erstmal gut aus, nun macht man einen normalen Aufruf des Programms:
... polling site [Tine 20 - Downloads] ... [Tine 20 - Downloads] Stable: Kristina (2013.03.8) [Tine 20 - Downloads] Beta: Collin (2013.10.1~beta2) 2 updates ...
Das sieht gut aus.
In der Zeile receiver den Empfänger entfernen, damit keine Emails gesendet werden:
receiver = ''
Der Arbeitspfad muss angepasst werden, da in diesem die Status-Dateien verwaltet werden:
os.chdir('/var/www/checker')
In der Zeile mit rssfile eine Datei eintragen, die als Feed generiert werden soll.
rssfile = '/var/www/ttrss/htdocs/checkerfeed.xml'
Die fertige config.py sieht dann so aus:
import os.path # remember to rename this file to "config.py" sites = [ {'shortname': 'VirtualBox', 'uri': 'https://www.virtualbox.org/', 'type': 'html', 'contentxpath': '', 'contentregex': 'VirtualBox.*released', 'encoding': 'utf-8'}, {'shortname': 'Tine 20 - Downloads', 'uri': 'https://www.tine20.org/download/download.html', 'type': 'html', 'titlexpath': "//div[contains(@class,'downloadArea')]//td[contains(@class, 'tableheader')]", 'contentxpath': "//div[contains(@class,'downloadArea')]//table[contains(@class, 'contenttable')]", 'encoding': 'utf-8'}, {'shortname': 'HostEurope Server', 'uri': 'https://hosteurope.de/Server', 'type': 'html', 'contentxpath': "//div[contains(@class,'container')]", 'regex': '', 'encoding': 'utf-8'} ] subjectPostfix = 'A website has been updated!' enableMailNotifications = False sender = 'news@domain' smtphost = 'domain' useTLS = False smtpport = 25 smtpusername = 'news@domain' smtppwd = 'mypassword' receiver = '' enableRSSFeed = True maxFeeds = 100 os.chdir('/var/www/checker/status') rssfile = '/var/www/ttrss.home.local/htdocs/checkerfeed.xml' # set to '' if you don't want the script to generate a RSS2 feed
Damit das Progamm nun regelmäßig (jede 30 Minuten) die Webseiten überprüft, fügt man die folgende Zeile in die Datei /etc/crontab
ein:
30 * * * * www-data cd /var/www/checker && env LC_ALL=en_GB.utf8 python3 MailWebsiteChanges.py
Beim ersten Abruf der Web-Seiten wird nur der Standardfeed erzeugt, ohne die überwachten Web-Seiten. Diese erscheinen erst, wenn sich nach dem ersten Abruf etwas ändert.
Wenn man z. B. die folgende Meldung erhält, dann passt etwas nicht mit den Einstellungen:
UnicodeEncodeError: 'ascii' codec can't encode character '\u2014' in position 11903: ordinal not in range(128)
In solch einem Fall muss man für den verwendeten Benutzer ein entsprechendes Locale einrichten; LC_ALL=„C“ funktioniert für viele Web-Seiten nicht, siehe auch hier.
Man kann auch direkt beim Aufruf eines Kommandos die locales angeben:
env LC_ALL="en_US.utf8" python3 MailWebsiteChanges.py
Das funktioniert natürlich nur, wenn die locale in der Datei /etc/locale.gen freigeschaltet ist, also keine Raute davor stehen hat. Ist dies nicht der Fall, dann muss man diese Raute entfernen und dann als Benutzer root oder mit sudo den Befehl
locale-gen
ausführen.
Nun kann man den generierten Feed von https://ttrss/checkerfeed.xml
in Tiny Tiny RSS eintragen, fertig :)
Ändert sich nun etwas auf einer der Web-Seiten, so steht z. B. Folgendes in Tiny Tiny RSS: