– WordPress Ministatistik, DIY –

Vor 2-3 Tagen hat WordPress die Ministatistik, wie ich sie in etwa oben nachgemalt habe – einen Screenshot habe ich nicht – aus der Ansicht geworfen. Wer selbst keinen Blog hat, kennt das gar nicht – auch ich bekomme die nur auf meinem eigenen Blog angezeigt, nicht auf dem anderer Leute. Das war ein Minibalkendiagramm, das stündlich aktualisiert wurde, wenn man die Seite neu lud, und die letzten 48 h umfasste, erinnerte, je nach Besucherzahlen, manchmal an das Ciscologo, welches seinerseits auch an eine Hängebrücke erinnert.
Wer einen Premiumaccount hat, kann da vielleicht auch eigene Widgets platzieren. In dem von mir verwendeten 0-8-15-Layout im Free-Tarif war das allerdings keine Option die man aus-, abwählen oder platzieren konnte.
Ich habe es gleich schmerzlich vermisst. Bei den Einstellungsoptionen fand ich keinen passenden Ersatz. Unter Design/Widgets/Blogstatistik fand ich lediglich einen Zähler aller Besucher, der, wenn man die Überschrift und die Einheiten löscht, so aussieht:

Den sehen jetzt alle, was mich nicht stört, außer der Platzverbrauch, aber man sieht natürlich nicht mehr wie viele pro Stunde da waren und muss die Zahl vom letzten Mal im Kopf haben, um daraus den jüngsten Verkehr abzuleiten. Nichts, womit ich mich belasten will, aber eine Basis um selbst was zu bauen.
Wer sein eigenes WordPressblog selbst hostet hat andere Möglichkeiten, aber da ich mich nicht um die Internas des Blogs kümmern will, absichern, Backups und das alles, muss ich mir anders behelfen.
Eine Webseite kann man auch programmgesteuert abrufen. Gut – das machen ja auch Firefox, Chromium, Safari und Opera, aber diese stellen sie auch grafisch dar. Man kann einfach den HTML-Code runterladen, und in diesem sieht der Zähler so aus (Zeilenumbrüche und Einrückung im Original anders):
<div id=“secondary“ class=“widget-area“ role=“complementary“>
<aside id=“blog-stats-4″ class=“widget widget_blog-stats“>
<h3 class=“widget-title“></h3>
<ul>
<li>184,914 </li>
</ul>
</aside>
Anhand der Zahl ist der Block leicht zu finden. Den Quellcode kann man sich auch im Browser ansehen, aber man will ja nicht stündlich die eigene Webseite manuell speichern, also das erledigt man mit wget:
wget https://demystifikation.wordpress.com/
für andere Webseiten eben mit einer anderen Adresse. Weil ich den Widget-Titel im Design gelöscht habe ist das leer bei mir. Gespeichert wird das runtergeladene unter index.html. Allerdings brauche ich gar nicht die ganze Datei sondern will da nur einen Teil aausfiltern, deswegen sage ich mit -O wo der Output hinsoll, und mit einem verlorenen Minuszeichen, dass es auf die Konsole ausgegeben werden soll.
wget -q https://demystifikation.wordpress.com/ -O -
Das -q steht für quiet und unterdrückt irgendwelche Statusmeldungen von wget, wieviel Prozent der Arbeit schon geleistet ist, und solchen Firlefanz.
Den Output filtere ich dann mit grep auf die Zeile, die den HTML-Code ‚<aside id=“blog-stats-4‘ enthält, wobei -A1 bewirkt, dass eine zusätzliche Zeile ausgegeben wird, und als zweiten Filter nutze ich sed, dem ich sage, dass ich vom Listitem nur die Folge an Ziffern und Kommazeichen will, und das Kommazeichen soll dann auch weg.
sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p"
Wer oft HTML, XHTML und XML-Code parsen muss wird vielleicht lieber zu einem Tool wie xmlstarlet greifen, welches den Vorteil hat, robust gegenüber Zeilenumbrüchen zu sein oder dem Vorkommen von Suchbegriffen in Kommentaren, aber das ist hier nicht zu erwarten. Sollte sich das HTML ändern, dann womöglich auch gleich soviel, dass einem das auchnicht weiterhilft.
Im ganzen sieht die Kette dann so aus:
counter=$(wget -q https://demystifikation.wordpress.com/ -O - | grep -A1 '<aside id="blog-stats-4' | sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p")
Jetzt steht in der Variablen counter nur noch die Zahl 184914 und gespeichert wurde gar nichts.
lastcount=$(< ~/.blogcounter)
increase=$((counter-lastcount))
#
old=$(date -r ~/.blogcounter +%s)
now=$(date +%s)
timespan=$((now-old))
#
heat=$(test $timespan -ge 0 && echo $((increase*3600/timespan)) || echo "--")
Dann sage ich
- lastcount soll der Inhalt der Datei ~/.blogcounter sein, eine versteckte Datei, die das Programm später selbst schreiben wird, so dass es beim ersten Mal einen Fehler meldet, weil die Datei nicht vorhanden ist.
- increase ist einfach die Differenz von altem Counter und Istzustand
- old ist der Zeitstempel der Datei Blogcounter in Sekunden seit dem 1.1.1970
- timespan ist die Zeitdifferenz zu now, also jetzt
heat=$(test $timespan -gt 0 && echo $((increase*3600/timespan)) || echo "--")
Heat sollen die mittleren Besucher pro Stunde sein seit der letzten Protokollierung, also wenn nach 30 Minuten 10 gezählt wurden 20 und wenn die Messung ausgefallen ist (Rechner aus) eventuell 5, wenn es nach 2 h 10 waren.
Getestet wird, ob die Zeitspanne > (greater than) 0 ist, dann sei heat der Wert der Berechnung, sonst „–“ (Division durch Null vermeiden!).
Jetzt wird es ein wenig kompliziert – wieso?
Nun, einmal will ich das Programm nutzen, um nur die stündlichen Differenzen zu protokollieren. Andererseits will ich jederzeit abfragen können ohne etwas zu protokollieren, etwa weil ein Beitrag von einem Alphablogger verlinkt wird, und plötzlich 1000e Besuche bekommt, so dass ich im 10-Minutentakt nachsehe, was das Volk macht.
test 1$# -gt 10 && test $1 = "-w" && echo $counter > ~/.blogcounter \
|| echo -e "Anzahl Anstieg /h Intervall (min) Messpunkt\n-------------------------------------------------------"
Das test 1$# ist ein furchtbarer Hack. $# ermittelt, wieviele Argumente einem Skript übergeben wurden. Aus unerfindlichen Gründen ist das aber nicht 0, wenn es keine Argumente sind, sondern nix, leer, nada, Nil, void, „“. Und dann scheitert der Test. Also klebe ich eine 1 davor und tesst nicht auf größer als 0, sondern auf größer als 10. Eigentlich müsste es da was eleganteres geben.
Waren es mehr als 0 Argumente prüfe ich, ob der Inhalt des 1. Arguments „-w“ war (w wie write, schreiben). Mit mehr oder anderen Argumenten rechne ich übrigens nicht.
War auch dies prima, dann, und nur dann schreibe ich die aktuelle Zahl in die versteckte Datei, die oben bereits erwähnt wurde. Ansonsten gebe ich eine Überschrift aus.
echo -e "$counter $increase $heat $((timespan/60)) $(date '+%H:%M %F')"
So oder so gebe ich dann die Werte aus, Zählerstand, Differenz, Seitenaufrufe /h seit letzter Messung und das Datum. So sieht ein isolierter Scriptaufruf (blogcounter.sh) aus:
Anzahl Anstieg /h Intervall (min) Messpunkt
-------------------------------------------------------
185203 0 0 22 20:22 2017-01-08
Etwas müde, gerade?
Seit 20 Uhr 0 Besucher, das sind 0 pro Stunde, Messintervall sind 22 Minuten und gemessen heute um 20:22 Uhr.
Außerdem hat Linux ja einen cron-Daemon, der chronologisch Dienste verrichten kann, wenn man im sagt wann und was. Den stellt man so ein:

hilfreiche Linuxdaemonen, im Hintergrund wirkend
0 * * * * /home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog
Das heißt jeweils zur Minute 0, jede Stunde (*), jeden Tag der Woche, des Monats usw. soll das Skript oben, das bei mir unter /home/stefan/bin/blogcounter.sh liegt ausgeführt werden, und die Ausgabe an die Datei /home/stefan/.bloglog angehängt werden (die erstellt wird, wenn sie noch nicht existiert). Das -w unterdrückt die Ausgabe der Überschrift, die man nicht für jede Zeile im Log haben will, und sorgt dafür, dass der Wert auch in die Datei ~/.blogcounter geschrieben wird.
Und dann gibt es noch ein kleines Script bloglog.sh, das so aussieht:
#!/bin/bash
#
# Blogtrafficlog der letzten 48 Stunden ausgeben
#
echo -e "Anzahl Anstieg Heat(/h) Intervall (min) Messpunkt"
echo "-------------------------------------------------------"
tail -n 48 ~/.bloglog | tac
Tail gibt nur die letzten 48 Zeilen der Datei ~/.bloglog aus, tac ist das Gegenteil von cat und gibt die Zeilen in umgekehrter Reihenfolge aus, also die jüngsten zuerst. Je nach Bildschirm und Fontgröße empfiehlt es siich, die Zahl an die eigenen Bedürfnisse anzupassen.
Die Ausgabe von bloglog.sh sieht beispielsweise so aus:
Anzahl Anstieg Heat(/h) Intervall (min) Messpunkt
-------------------------------------------------------
185205 1 1 60 22:00 2017-01-08
185204 1 1 60 21:00 2017-01-08
185203 22 21 60 20:00 2017-01-08
185181 0 0 59 19:00 2017-01-08
185181 4 4 60 18:00 2017-01-08
185177 10 10 60 17:00 2017-01-08
185167 3 2 60 16:00 2017-01-08
185164 7 7 59 15:00 2017-01-08
185157 4 4 60 14:00 2017-01-08
185153 3 3 60 13:00 2017-01-08
185150 185150 187177 59 12:00 2017-01-08
-185118 -183134 60 11:00 2017-01-08
185118 16 16 60 10:00 2017-01-08
185102 5 4 60 09:00 2017-01-08
185097 0 0 59 08:00 2017-01-08
185097 0 0 60 07:00 2017-01-08
...
Das genaue Layout kann mit WordPressmitteln nicht ohne übermäßigen Aufwand getreu wiedergegeben werden – ich denke so geht es.
Die zwei Zeilen, die hervortreten deuten darauf hin, dass der Counter um 11:00 nicht lesbar war, auf Null gesetzt wurde, so dass die Zahl einbrach um dann hochzuschnellen – ein Grund dafür ist mir nicht erkenntlich, aber es zeigt, dass das Skript insofern robust ist, als es 2 Stunden später wieder brav seinen Job tut.
Pro Stunde fallen ca. 25 Bytes Daten an, das macht 600 am Tag, rd. 220.000 im Jahr und in 100 Jahren 22 MB – dürfte also, selbst wenn es vergessen wird und ständig, über viele Systemaktualisierungen weiterläuft, nie Probleme verursachen.
Hier nochmal das ganze blogcounter.sh-Skript am Stück:
#!/bin/bash
#
# Blogcounter ermitteln
# Zahl erfassen
# Differenz zur letzten Messung berechnen
# Differenz ausgeben
# Zahl speichern
# Zeit der letzten Messung erfassen
# Anstieg ermitteln
# Hits pro Stunde ermitteln
#
counter=$(wget -q https://demystifikation.wordpress.com/ -O - | grep -A1 '<aside id="blog-stats-4' | sed -nr "s/.*<li>([0-9,]+).<\/li>.*/\1/;s/,//p")
lastcount=$(< ~/.blogcounter)
increase=$((counter-lastcount))
#
old=$(date -r ~/.blogcounter +%s)
now=$(date +%s)
timespan=$((now-old))
#
heat=$(test $timespan -gt 0 && echo $((increase*3600/timespan)) || echo "--")
# only write to counter file if param -w was given
# allows for hourly logged values, triggered by cron (with -w) and
# intermediate views without logging
test 1$# -gt 10 && test $1 = "-w" && echo $counter > ~/.blogcounter || echo -e "Anzahl Anstieg /h Intervall (min) Messpunkt\n-------------------------------------------------------"
#
# Ergebnisse loggen. Das ganze sollte per cron stündlich laufen. Mit e. Script
# die letzten 24 oder 48 Messungen anchauen.
#
# Crontabzeile:
# 0 * * * * /home/stefan/bin/blogcounter.sh -w >> /home/stefan/.bloglog
#
echo -e "$counter $increase $heat $((timespan/60)) $(date '+%H:%M %F')"
Weiterführende Hilfe bekommt man zu den einzelnen Befehlen mit
- man wget
- man sed
- man tail
- man date
- man bash
- help test
- man tac
- man cron
- man crontab
und zu allen Befehlen, außer test, (was ein Kommando der Bash ist) auch mit PROGRAMM –help.