Blog

PhantomJS Datenauswertung & BASH Datenanalyse

Joshua Appelman

Joshua Appelman

Aktualisiert Oktober 22, 2025
6 Minuten
CasperJS Als mittelgroßes Unternehmen mieten wir für unsere Mitarbeiter Postfächer bei einem Hosting-Anbieter; eine Menge Postfächer. Diese gibt es in verschiedenen Größen, und je größer sie sind, desto teurer werden sie natürlich. Neulich erhielt ich eine E-Mail, in der mehrere neue Konten angefordert wurden, und wollte diese gerade anlegen, als ich auf eine scheinbar ineffiziente Zuweisung stieß. Der Benutzer hatte ein mittelgroßes Konto, das etwa 150 € pro Jahr kostete, während er anscheinend mit dem kleinsten Konto für etwa 50 € pro Jahr auskommen konnte. Das machte mich natürlich neugierig auf unsere anderen Zuweisungen und ich suchte nach einer Übersicht über die Nutzung aller unserer E-Mail-Konten. Kein Glück. Die einzige Möglichkeit, um zu sehen, wie viel des gemieteten Speicherplatzes tatsächlich genutzt wurde, bestand darin, durch die - nicht-restliche und zustandsabhängige - Weboberfläche unseres Hosting-Anbieters zu navigieren und die Statistiken für jeden einzelnen Benutzer aufzurufen. Herausforderung angenommen! In letzter Zeit bin ich es leid, Selenium zu verwenden, und wollte mir einige PhantomJS-basierte Alternativen ansehen. Dabei fiel mein Blick auf CasperJS und ich beschloss, es auszuprobieren. Mit brew habe ich die neueste Entwicklungsversion heruntergeladen: [shell] $ brew update $ brew install casperjs --devel [/shell] Das gesamte Skript finden Sie in diesem Gist, wobei Sie pro Abschnitt gehen: [javascript] var casper = require('casper').create({ verbose: true, logLevel: 'info' }); var credentials = JSON.parse(require('fs').read('./credentials.json')); var url = 'private'; casper.start(url + '/user/login', function() { this.fill('form#login_form', credentials, true); }); [/javascript] Die erste Zeile initialisiert CasperJS, wobei eine gewisse Protokollierung aktiviert ist. Die zweite Zeile liest eine einfache json-Datei ein, die die Formularfelder und Werte der Anmeldeseite enthält, während die dritte Zeile die Basis-URL unseres Hosting-Anbieters enthält.Im nächsten Abschnitt wird Casper angewiesen, zur Anmeldeseite dieser URL zu navigieren, das angegebene Formular mit den Anmeldedaten auszufüllen und abzuschicken. So einfach ist das! [javascript] casper.thenOpen(url + '/subscription/config/xebia.com/exchange_mailbox', function() { this.getElementsInfo('tr td a').forEach(function (node) { if (node.attributes.nicetitle === "View") { [/javascript] Alle eingeloggt, ist es Zeit, zur Übersichtsseite der Börse zu navigieren. Hier sind die Kontodaten eines jeden Benutzers in einem Knoten mit dem Attribut nicetitle="view" verlinkt. Natürlich wollen wir über diese Informationen iterieren. An dieser Stelle gab es einen kleinen Haken im Plan: Die HTML-Datei ist völlig unstrukturiert. Es handelt sich einfach um eine Tabelle mit verschiedenen Dimensionen und Paaren von Bezeichnungen und Werten. Ich beschließe, das Problem zu verschieben und vorerst einfach das gesamte Element zu holen: [javascript] casper.thenOpen(url + node.attributes.href, function() { require('fs').write('output', JSON.stringify(this.getElementInfo('div.contentleft').html, 'a')); }); } }); }); [/javascript] Das Ganze endet mit a: [javascript] casper.run(); [/javascript] Jetzt ist es an der Zeit, in die Konsole einzutauchen und es auszuprobieren: [shell] $ casperjs fetch.js [/shell] Ausgezeichnet! Casper macht sich an die Arbeit, entdeckt und holt die Daten und ich kann sehen, wie ein Teil der generierten Ausgabedatei hereinströmt. Nicht lesbar, aber die Daten sind alle da, was uns zum zweiten Thema dieses Beitrags bringt.

BASH-Datenanalyse:

Beginnen wir mit dieser missgebildeten HTML-Datei mit aufräumen. Da uns die vielen Warnungen, die tidy ausgibt, nicht interessieren, leiten wir stderr nach /dev/null um und erhalten so das Ergebnis:
Ordentliches  <geholt 2>/dev/null
  ntttt</pre>
<div  Klasse=""klar""></div>
<vor>ntt</pre>
<div>nttt<Etikett>Aktuelle Mailboxgröße</label>nttt1921
MBntt</div>
<vor>ntt</pre>
<div>nttt<Etikett>Warnquote</label>nttt2250
MBntt</div>
<vor>ntt</pre>
<div>nttt<Etikett>Sendequote blockieren</label>nttt2375
Da, wie bereits erwähnt, alle interessanten Felder ein 'label'-Tag enthalten, suchen wir nach diesen:
Ordentliches  <geholt 2>/dev/null | grep label</pre>
<div>nttt<Etikett><Etikett>E-Mail
</label></label>
<div>nttt<Etikett>E-Mail-Aliase</label>nttt
<div>nttt<Etikett>Aktuelle Mailboxgröße</label>nttt1921
<div>nttt<Etikett>Warnquote</label>nttt2250
<div>nttt<Etikett>Sendequote blockieren</label>nttt2375
<div>nttt<Etikett>Senden und Empfangen blockieren
Quote</label>nttt2500 MBntt</div>
<div>nttt<Etikett>Pop aktiviert</label>nttt<img  alt="" src="<br" 
/>
Okay, das sieht schon ganz gut aus. Schneiden wir alles vor den abschließenden Label-Tags weg und entfernen die Zeichen n und t.
Ordentliches  <first-fetch 2>/dev/null | grep label | sed  's/^.*/label>//'  |
sed  's/\nt//g'
<div><Etikett><Etikett>Tauschen Sie
</label></label>
<div><Etikett>SMTP
1921
2250
2375
2500 MB</label></div>
<Etikett><Etikett>
<img  alt="" src="<br" 
/><img  alt="" src="<br" 
/>...
Lassen Sie uns einige der uninteressanten Zeilen herausfiltern, um sie zu bekommen:
Ordentliches  <first-fetch 2>/dev/null | grep label | sed  's/^.*/label>//'  |
sed  's/\nt//g'  | grep -v  'label|img|<br>|HOSTED'
Sunil Prakash
Sunil Prakash
REDAKTIERT</pre>
</div>
REDAKTIERT</div>
1921
2250
2375
2500 MB
Nach dem Entfernen des nachgestellten div und der MB's haben wir endlich bereinigte Daten:
Ordentliches  <first-fetch 2>/dev/null | grep label | sed  's/^.*/label>//'  |
sed  's/\nt//g'  | grep -v  'label|img|<br>|HOSTED'  | sed 's/<.*//' | sed 's/ MB$//'
Sunil Prakash
Sunil Prakash
REDAKTIERT
REDAKTIERT
1921
2250
2375
2500
Die wir in einer Datei namens 'data' ablegen. Wenn Sie diese Zeilen in Achtergruppen einfügen, die durch Kommas getrennt sind und die leeren Felder mit einem Punkt aufgefüllt werden, erhalten wir das Ergebnis:
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'  | head -n 2
REDACTED,REDACTED,REDACTED,REDACTED,1921,2250,2375,2500
REDIGIERT,REDIGIERT,REDIGIERT,REDIGIERT,40,2250,2375,2500
Wenn Sie dies durch awk leiten, den Feldbegrenzer auf Komma setzen und das letzte Feld geteilt durch das vierte berechnen, erhalten Sie folgendes Ergebnis:
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'  |
awk -F,  {print $0 "," $5/$8*100"%" }'  | head -n 2
REDACTED,REDACTED,REDACTED,REDACTED,1921,2250,2375,2500,76.84%
REDACTED,REDACTED,REDACTED,REDACTED,40,2250,2375,2500,1.6%
Schließlich ist es an der Zeit, nach dem letzten kommagetrennten Feld, dem Nutzungsprozentsatz, in umgekehrter numerischer Reihenfolge zu sortieren:
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'  | awk -F,  '{print $0 "," $5/$8*100"" }'  |
sortieren -t, -k +9 -n -r | tail -n 2
REDIGIERT,REDIGIERT,REDIGIERT,REDIGIERT,0,2250,2375,2500,0
REDIGIERT,REDIGIERT,REDIGIERT,REDIGIERT,0,225,237,250,0
Und wir finden bereits zwei leere Postfächer, die zumindest auf das billigste Paket heruntergestuft werden könnten! Um die Dinge besser lesbar zu machen, sollten wir sie in einer schönen Spalte anordnen
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'  | awk -F,  {print $0 "," $5/$8*100 }'  |
sortieren -t, -k +9 -n -r | Spalte -t -s , | Schwanz -n 5
REDIGIERT REDIGIERT REDIGIERT 1 2250 2375 2500 0.04
REDIGIERT REDIGIERT REDIGIERT 0 225 237 250 0
Und schon haben wir einen Überblick über die Nutzung aller unserer Postfächer. Lassen Sie uns nun awk verwenden, um nach den Postfächern zu filtern, die ein Paket verwenden, das größer als das Minimum (250 MB) ist und weniger als zehn Prozent ausnutzen, da diese definitiv heruntergestuft werden können:
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'  |
awk -F,  {print $0 "," $5/$8*100 }'  | Sortieren -t, -k +9 -n -r |
awk -F,  '{ if ($8 > 250 && $9 < 10) print $3 "," $9"%" }'  |
Spalte -t -s,
GEKÜRZT 0.32%
VERKÜRZT 0.2%
Und schon haben wir eine ganze Liste von Konten, auf denen leicht gespart werden kann. Lassen Sie uns zum Schluss noch schnell ausrechnen, wie viel wir gerade gespart haben:
cat data | paste -d , - - - - - - - - - | sed  's/,,/,.,/'x |
awk -F,  '{ if ($8 > 250 && ($5/$8) < 10) print $0}''  |
wc -l | xargs  echo "100 *"  | bc
6100
Es sieht so aus, als hätten wir durch zwei Stunden Spielerei mit CapsperJS, tidy, sed, awk und grep gerade €6100 gespart, und wahrscheinlich sogar noch mehr, wenn ich mir die Daten etwas genauer ansehe. Kein schlechtes Ergebnis für 18 Zeilen Javascript und ein paar Zeilen BASH!

Verfasst von

Joshua Appelman

Contact

Let’s discuss how we can support your journey.