Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

Simpler Bot zum Auslesen entfernter Formular-Seiten

Abfrage und Auswertung mit PHP und cURL

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.

Aufgabenstellung und Umsetzung

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. Zu­sätz­lich 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.

Einzelheiten und Beschreibung

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)."&param=".$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.

 

Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen