Da ist also dieses Forum. Mit den vielen interessanten Beitraegen in vielen Threads in vielen Unterforen. Und dann ist da dieser Geisteswissenschaftler, der sich mit dem Forum auseinandersetzen will. Der moechte dazu aber nicht jeden Forenbeitrag einzeln mittels Copy'n'Paste uebernehmen. Sondern lieber jeden Thread als (Text)Datei haben. Und nun?

Problemstellung

Das Forum ist ein klassisches phpbb ohne grossen Spielkram. Theoretisch besteht auch Zugriff auf die Datenbank und die Moeglichkeit, PHP-skripte auf dem Server auszufuehren. Und dann kommt das "aber": Wollte man die Aufgabenstellung auf diesem Wege angehen, so muesste man ein paar Kenntnisse mitbringen:

Aus den Fragen ergibt sich direkt die Grundalgorithmik eines Programms zur Loesung des im Teaser erwaehnten Problems:
flst := getUnterForen()
for each f in flst:
	fname := getUnterForenName(f)
	tlst := getThreadList(f)
	for each t in tlst:
		tname := getThreadName(t)
		dumpToFile(fname, tname, getThreadCotents(t))
Das sieht doch eigentlich ganz harmlos aus, oder?

Loesungsmoeglichkeiten

Der erste Gedanke -- das kann man doch einfach runterimplementieren. Der zweite: Das wird eklig. Denn ein Thread liegt in der Datenbank nicht so einfach und friedlich greifbar, wie man sich es wuenschen wuerde. Denn auf dem Weg vom Browser zur Datenbank gibt es noch die Station "Normalisierung & Optimierung". Die sorgt dafuer, dass da z.B. nicht mit jedem Beitrag wieder der Nutzer als Nutzername mit allem, was zu diesem Nutzer angezeigt werden soll (Name, Status, Credit Points, Ort, ...) abgelegt wird. Stattdessen steht da eine Nutzer-ID. Ueberhaupt wird idealerweise jede Information nur einmal konkret in der Datenbank abgelegt und danach ausschliesslich ueber Nummern referenziert. Da freut sich der Datenbaenkler.
Ich nicht.
Also habe ich mich auf die Suche nach einem Datenbankschema fuer phpbb gemacht. Und habe so etwas in der Art gefunden. Ich muss anmerken, dass sich zu diesem Zeitpunkt meine Freude bereits steil auf die x-Achse zu knallen drohte. Dann mal kurz eine Runde nachgedacht. Man denke kurz an das nach Pareto benannte Prinzip. Mit 20% des Aufwandes lassen sich 80% des Ergebnisses erreichen. Die Frage ist also, welche 20% der perfekten Loesung verzichtbar sind, um die Aufgabe immer noch loesen. Danach kann man die Aufgabe dann so umsortieren, dass man mit 20% des in diesem Moment befuerchteten Aufwandes zur Loesung kommt....
Logische Frage also: Was waere die perfekte Loesung?

Wenn ich mich nun entscheide, auf alle Punkte ausser den ersten dreien zu verzichten (also all das, was ein Programm schoen macht, aber nichts zur Loesung des Problems beitraegt), dann kommt auch noch eine zweite Moeglicheit in Betracht, wie man das Problem loesen kann. Webscraping! :)

Webscraping!

Was bedeutet nun Webscraping? Man nehme sich das Forum in der Webansicht und dann arbeite man sich dort durch den HTML-Quelltext. Der Algorithmus verkommt also zu einer Sequenz mehr-oder-weniger eleganter "Hole die Datei der URL X" und "Durchlaufe die Datei x und tue damit folgendes..."-Aufrufe. Im Konkreten faengt es so an: "Hole die Startseite mit den Unterforen. Durchsuche sie nach Links, die mit "viewforum.php" beginnen (also die Threadlisten eines Unterforums bilden). Sammle diese Links (wenn man will, gleich mit den Unterforennamen), zum Beispiel in einer Textdatei. Dann gehe im naechsten Schritt diese Textdatei durch, hole jede URL, die mit "viewforum.php" beginnt und extrahiere die Threads (deren Links beginnen mit "viewtopic.php"). Cave: Spaetestens hier sollte man Mehrseitigkeit beherrschen! Das Spielchen wiederholt sich nun nochmal mit den einzelnen Threads (die ebenfalls mehrseitig sein koennen). Wie bekommt man nun die einzelnen Threads in Textdateien ueberfuehrt, ohne dass es ganz und gar fuerchterlich wird? Dazu kann man ja den guten alten Lynx einspannen. Der frisst HTML und erzeugt feinsten Text-Output. Der kommt nun in eine Adaequat benannte Datei (ein sed 's/[^ A-Za-z0-9]//g' sorgt fuer ungefaehrliche Dateinamen aus den Titeln) und voila. Damit die Threads nicht gar so schlimm aussehen gibt es noch einen kleinen aber fiesen Trick: Einzelne Threads haben bei phpbb eine Drukansicht, die sich auf das Benoetigte (Timestamp, Autorenname, Beitragstitel und -inhalt) beschraenkt :)

Einen Vorteil des Scraping-Ansatzes sollte man nicht vergessen: Es funktioniert ohne Kooperation des Seitenbetreibers. Es ist voellig irrelevant, ob Datenbankzugriff besteht oder nicht. Das spart gegebenenfalls Buerokratie, Fragen, Antworten. Es erzeugt potentiell Wut, Frustration, Ohnmacht.

Manoeverkritik

Job erledigt, keine Kollateralschaeden angerichtet, Truppe vollzaehlig aus der Mission zurueckgekehrt. Haette eleganter laufen koennen, aber ausser einer leichten Prellung am Stolz hat sich keiner was getan. Neben dem Missionsziel wurde unerwartet ein Trueffel gefunden.

Die Dateien und wie man sie benutzt

In der down/scrapephpbb.tar (deren Inhalte, es sei angemerkt, unter BSD-Lizenz stehen). Wie benutzt man das nun? Einfach: Man editiere die Datei start.sh und aendere hierin die BASEURL auf das virtuelle Verzeichnis, in dem das Forum residiert. Wenn also das Forum z.B. seine Startseite unter http://example.com/forum/index.php hat, dann ist als BASEURL http://example.com/forum/ anzugeben. Wichtig ist insbesondere der letzte Slash. Dann begebe man sich mit einer Shell in das Verzeichnis, in dem das Skript residiert und fuehre es aus. Entweder es klappt dan -- oder nicht. Ersteres: Glueckwunsch. Letzteres: Beileid. Und nein, da werde ich keinen weiteren Support leisten. Das ist etwas, was in die ueberfluessigen 80% faellt...
Wenn es nicht klappen will, kommt man aber vielleicht mit einem Blick in die Quelltexte des Forums weiter :)
Vielleicht noch ein Wort zu den erwarteten Dependencies, also welche anderen Programme im Pfad vermutet und mit der auf FreeBSD vorhandenen Semantik als ausfuehrbar vorausgesetzt werden:

Stichworte:


Impressum