Mailwebsitechanges

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.

Ziel dieser Anleitung

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.

Installation

Abhängigkeiten installieren

Als root:

apt-get install python3-lxml

Umgebung vorbereiten

mkdir /var/www/checker

cd /var/www/checker

Aktuelle Version herunterladen und entpacken

wget https://github.com/Debianguru/MailWebsiteChanges/archive/master.zip

unzip -j master.zip

Verzeichnisrechte einstellen

Nun geben wir dem Benutzer www-data noch die Zugriffsrechte für sein neues Spielzeug:

chown -R www-data: /var/www/checker

Konfiguration

Hilfen

  • Eine kleine Liste von XPath-Elementen im Vergleich zu CSS-Selektoren gibt es hier.
  • Eine detaillierte Einführung zu XPath findet man hier.

Config erstellen und anpassen

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…

Werte pro Seite

  • shortname, verpflichtend
    Diesen Namen verwendet man für --dry-run
  • uri, verpflichtend
    Die URL der zu überprüfenden Webseite
  • type, optional
    xml, text oder html
  • titlexpath, optional
  • titleregex, optional
  • titlecss, optional
  • contentxpath, optional
  • contentregex, optional
  • contentcss, optional
  • encoding, optional
    Normalerweise utf-8, bei Deutsch-sprachigen Seiten auch mal ISO-8859-9.
    Schaut man in den Quelltext einer Web-Seite, so kann man nach CHARSET=xxx suchen, um das Encoding zu erhalten.

Die Dokumentation aller Werte gibt es hier.

Einträge testen

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.

Email?

In der Zeile receiver den Empfänger entfernen, damit keine Emails gesendet werden:

receiver = ''

Weitere Einstellungen

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'

Fertige Konfigurationsdatei

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

Regelmäßige Überprüfung per Cron einrichten

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

<WRAP center round important> 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. </WRAP>

Bekannte Probleme

Encoding

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.

Feed in Tiny Tiny RSS einbinden

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:

Zuletzt geändert: 2023-04-07 18:38:12 +0200 CEST: tag -> tags und categories