Ein kleiner Bot, geeignet zum Auslesen von entfernten Formular-Seiten, lässt sich mit PHP relativ
einfach realisieren. Eigentlich handelt es bei den auszulesenden Seiten nicht direkt um die Webseiten, in denen die
HTML-Formulare eingebunden sind, sondern um die Abfrage und Auswertung der Seiten, welche die Antworten auf die übermittelten
Benutzereingaben enthalten. Bei der überwiegenden Mehrheit von Webanwendungen, welche der Suche oder der Auswahl dienen, ist
jedoch die das Formular enthaltende HTML-Seite gleichzeitig auch die Webseite, welche die Antworten ausgibt.
Auf einem entfernten Server wurde unter der Domain www.example.com eine
Seite mit einem Formular unter den Datei-Namen response.php abgelegt, wobei diese Seite auch
gleichzeitig die Antworten auf die Benutzereingaben liefert. Nun soll für eine Abfrage jedoch nicht die URL www.example.com/response.php aufgerufen werden, sondern die Abfrage soll von einer Webseite erfolgen,
die unter einer anderen Domain erreichbar ist und das ohne diese andere Webseite zu verlassen.
Für die Umsetzung der Aufgabenstellung wird zuerst eine HTML-Seite mit einem Formular benötigt, die auf einem beliebigen
Server gespeichert werden kann. Zusätzlich wird eine zweite Seite auf einem anderen Server benötigt, die ebenfalls ein
Formular enthält, sowie den Code für einen simplen Bot.
Handelt es sich bei der Ursprungsseite um eine Seite mit einem Formular, welches die Benutzereingaben als
Parameter-Werte-Paare in einem QueryString mit der HTTP-Request-Methode GET übergibt, sieht die Angelegenheit relativ einfach
aus, denn in diesem Fall könnte die Datei einfach nur mit der PHP Funktion file_get_contents wie im nachfolgenden Beispiel
eingelesen werden.
<?php $data = file_get_contents("http://www.example.com/response.php?q=was"); // Auswertung und Weiterverarbeitung von $data ?>
Etwas komplizierter, doch in vielen (wenn auch nicht in allen) Anwendungsfällen realisierbar,
wird die Angelegenheit, wenn die eingegebenen Daten vom Formular mit der HTTP-Request-Methode POST übergeben werden. Die
nachfolgenden Code-Listings beziehen sich, um die Aufgabenstellung mit POST-Anfragen umzusetzen, auf die HTTP-Request-Methode
POST.
Beim ersten Code-Listing handelt es sich lediglich um eine Beispielseite mit einem Formular, wobei im
einleitenden Form-Tag des Formulars die Request-Methode POST anzugeben ist. Der restliche Code dient nur als Bestätigung für
erfolgte Eingaben bei Benutzung des Formulars.
Beispiel Formular-Seite (response.php):
<!DOCTYPE html> <html> <head> <title>Response-Seite zur Beantwortung von Fragen</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> </head> <body style="text-align:center"> <h1>Response</h1> <p>Antworten auf gestellte Fragen.</p> <form action="response.php" method="post" charset="windows-1252"> <input type="text" name="thema"> <input type="hidden" name="param" value="1"> <input type="submit" value="Suche"> </form> <div id="R01"> <?php error_reporting(E_ALL); /*--------------------------------------------------------------------- Kontrolle, ob eine Anfrage per HTTP-POST-Request gestellt wurde und die Parameter "thema" und "param" mit Werten belegt sind. ---------------------------------------------------------------------- */ if (isset($_POST["thema"]) and !empty($_POST["thema"])) { $them = trim($_POST["thema"]); $them = preg_replace("/[^a-zÄÖÜäöüß0-9s-]/i", "", $them); if (isset($_POST["param"]) and !empty($_POST["param"])) { $wert = trim($_POST["param"]); $wert = preg_replace("/[^0-9]/", "", $wert); } else {$wert = 1; } echo "Es wurde eine Antwort auf die Frage "".$them."" ". "mit dem Parameter ".$wert." gefunden.n"; } else {echo "Es wurde noch keine Anfrage übermittelt."; } ?> </div> </body> </html>
Das zweite Code-Listing enthält ebenfalls ein Formular für Benutzereingaben. Die Besonderheit besteht
lediglich darin, dass innerhalb des einleitenden Form-Tags beim Attribut Action nicht die URL der entfernten Seite angegeben
wird, sondern die Seite bot.php. Der Dateiname ist selbstverständlich frei wählbar und soll im Beispiel nur verdeutlichen,
dass die Seite ein simples Bot-Script enthält. Die Aufgabe des Bots ist es, die Benutzereingaben an die URL der Seite
response.php zu senden, die Antwort auszulesen und auf der Seite bot.php auszugeben.
Wichtig dabei ist, dass die Anzahl der Input-Elemente und die Werte der Type-Attribute des Formulars mit denen des entfernten
Formulars übereinstimmen. Die Namen der Input-Elemente können sich hingegen unterscheiden, da die Aufgabe des Formulars von
der bot.php nur darin besteht, die Benutzereingaben an das Bot-Script zu übermitteln. Die Übergabe der Benutzereingaben an das
Bot-Script kann ebenfalls per Post erfolgen, doch auch eine Übergabe per GET wäre möglich.
Vor der Verwendung sollten die eingehenden Daten geprüft werden, was im Beispiel mit der Funktion preg_replace und zwei
geeigneten Zeichenklassen als reguläre Ausdrücke erfolgt. Nach dieser Prüfung werden die Parameter-Werte-Paare wie bei einem
QueryString zusammengestellt und mit & verbunden. Falls erforderlich, sollten die Werte URL-kodiert werden. Im Gegensatz zu
den Namen des clientseitigen Formulars, müssen die Namen der Parameter im String mit den Namen der Input-Elemente des
entfernten Formulars übereinstimmen.
Der Aufbau der Verbindung und die Initialisierung der Session erfolgt mit cURL. Beim Request wird im Beispiel der aktuelle User
Agent durchgereicht, doch auch ein eigener User Agent könnte gesetzt werden. Als Besonderheit ist zu beachten, dass abweichend
vom Standard die HTTP-Request-Methode POST durch das Setzen der entsprechenden Optionen gewählt wird. Im Einzelnen betrifft
dies die Optionen CURLOPT_POST und CURLOPT_POSTFIELDS.
War der Verbindungsaufbau erfolgreich, wird nicht die komplette Response ausgegeben, sondern mit einer DOM-Methode nur der
Inhalt des Elementes ausgelesen (bzw. ausgekratzt oder ausgeschabt), welches die Antwort auf die übermittelten
Benutzereingaben enthält. Somit könnte das Bot-Script eigentlich auch als Scraper bezeichnet werden. Im Beispiel handelt es
sich dabei um den Inhalt des DIV-Bereiches mit der id R01 in der response.php.
Beispiel Formular mit Bot-Script (bot.php):
<!DOCTYPE html> <html> <head> <title>Testbot</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> </head> <body style="text-align:center"> <h1>Testbot</h1> <form action="bot.php" method="post" charset="windows-1252"> <input type="text" name="suche"> <input type="hidden" name="param" value="1"> <input type="submit" value="Suche"> </form> <?php error_reporting(E_ALL); $seite = "http://www.example.com/response.php"; // auszulesende Antwortseite /*-- Funktion für Request und Response ------------------------------*/ function vermittleMessage($request) { /*-- Aktuellen User Agent auslesen und auf Vorhandensein prüfen -*/ $agent = htmlspecialchars($_SERVER["HTTP_USER_AGENT"]); if (isset($agent) and !empty($agent)) { /*-- Übermittelte Werte vom Formular prüfen -----------------*/ if (isset($_POST["suche"]) and !empty($_POST["suche"])) { $them = trim($_POST["suche"]); $them = preg_replace("/[^a-zÄÖÜäöüß0-9s-]/i", "", $them); if (isset($_POST["param"]) and !empty($_POST["param"])) { $wert = trim($_POST["param"]); $wert = preg_replace("/[^0-9]/", "", $wert); } else {$wert = 1; } /*-- Werte gegebenfalls URL-kodieren --------------------*/ $pawe = "thema=".urlencode($them)."¶m=".$wert; /*--------------------------------------------------------- Eine cURL-Session initialisieren und Optionen für die HTTP-Request-Methode POST setzen. ---------------------------------------------------------- */ $ch = curl_init($request); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_USERAGENT, $agent); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $pawe); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); if (curl_exec($ch) !== false) {$response = curl_exec($ch); } else {$response = "Fehler: ".curl_error($ch); } curl_close($ch); return $response; } else {$response = false; } } else {$response = false; } return $response; } /*-- Die Funktion aufrufen ------------------------------------------*/ $data = vermittleMessage($seite); /*-- Nur den Inhalt des Elementes mit der ID R01 auslesen. ----------*/ if ($data != "") { $dom = new DOMDocument(); $dom->loadHTML($data); $res = $dom->getElementById("R01")->nodeValue; echo htmlspecialchars(utf8_decode($res)); } ?> </body> </html>
Wichtiger Hinweis: Wir möchten ausdrücklich betonen,
dass das Code-Listing auf dieser Seite nur als Demo zur Veranschaulichung sowie zur Erprobung in einer Testumgebung gedacht ist.
Einen Einsatz des Scripts für unlautere oder rechtlich bedenkliche Zwecke möchten wir hingegen in keiner Weise fördern.
Weiterhin wird das Script nicht in jedem Fall wie erwartet funktionieren, zum Beispiel dann nicht, wenn bei der entfernten Seite
Ajax-Technologien zur Anwendung kommen.
Einstieg in PHP
Übersicht
Diverse Themen