Dennis Parsch - IT-Dienstleistungen & Webdesign


Infotext der Firma

PHP - Website auslesen

Motivation

Haben Sie nicht schon einmal daran gedacht auf Ihrer Internetseite Informationen zum Wetter etc. auszugeben? Sie wissen aber nicht wie Sie von tausenden Städten Informationen immer aktuell halten sollen? Lassen Sie dass mal lieber das Problem anderer sein! Sie können sich diese Information von anderen Wesbsites oder sogenannten Programmierschnittstellen (APIs) laden.

Wichtig

Es gibt Funktionen, mit denen man bereits komplette Websites laden kann, allerdings lässt sich über diese der Datenfluss schlecht kontrollieren. Warum sollte man mehr von einer Seite laden, als man wirklich benötigt? Kommunikation zwischen zwei Servern ist zeitaufwendig und kann die Ladezeiten ihrer Website erhöhen. Deshalb werde ich auf die alte Methode mit fsockopen() eingehen.

Los geht's

Das Definieren der Socket-Variable, die wir später verarbeiten:
$socket = fsockopen("tcp://91.121.116.185", 80, $errno, $errstr, 5);
Wir öffnen einen sogenannten Socket, der eine Verbindung zu "91.121.116.185" herstellt, und speichern diesen in der Variable $socket ab. Der Port wird über den zweiten Parameter übergeben - hier Port 80. Falls ein Fehler auftreten sollte, speichert PHP die Fehlernummer in $errno und die Fehlermeldung in $errstr ab. Der letzte Parameter gibt die Wartezeit (in Sekunden) für ein Time-out an.

Das Senden eines GET-Request:
$newLine = "\r\n";

$header  = "GET / HTTP/1.0".$newLine;
$header .= "Host: www.dennis-parsch.de".$newLine;
$header .= "User-Agent: ".$_SERVER['HTTP_USER_AGENT'].$newLine;
$header .= "Referer: http://www.adresse-vorher.de/".$newLine;
$header .= $newLine;

fwrite($socket, $header);

Das Senden eines POST-Request:
$newLine = "\r\n";
$postDaten = "feld1=eingabe";

$header  = "POST / HTTP/1.0".$newLine;
$header .= "Host: www.dennis-parsch.de".$newLine;
$header .= "User-Agent: ".$_SERVER['HTTP_USER_AGENT'].$newLine;
$header .= "Referer: http://www.adresse-vorher.de/".$newLine;
$header .= "Content-Type: application/x-www-form-urlencoded".$newLine;
$header .= "Content-Length: ".strlen($postDaten).$newLine;
$header .= $newLine.$postDaten;

fwrite($socket, $header);

Nun haben wir dem Zielserver gesagt, was wir wollen. Bei den von uns gesendeten Requests handelt es sich um HTTP-Requests.
Nun die Erklärung:
$newLine Eine Variable, die als Inhalt einen Zeilenumbruch hat
GET / HTTP/1.0 Der erste Teil gibt die Art des Zugriffs an: GET
Der zweite Teil das Verzeichnis, auf das zugegriffen werden soll.
Der dritte Teil gibt die Version des gesendeten Requests an.
Host: www.dennis-parsch.de Nun will der Server wissen, über welche Domain wir auf ihn zugreifen, damit er uns den angeforderten Inhalt zurückgeben kann.
User-Agent Sagt dem Server, mit welchem Browser auf ihn zugegriffen wird.
$_SERVER['HTTP_USER_AGENT'] Eine vordefinierte Variable von PHP, die den aktuell genutzten Browser speichert.
Referer Übergibt dem Server die Internetadresse, von der wir kommen.
Content-Type Muss beim POST-Request vorhanden sein (siehe HTTP Post Request)
Content-Length Muss beim POST-Request vorhanden und sagt dem Server wie größ die Datenmenge ist, die wir an ihn schicken.
letzte Zeile In ihr werden beim POST-Request die Daten übergeben.
fwrite($socket, $header); Sendet den vordefinierten Header an den Server.

Nachdem wir nun eine Anfrage an den Server gesendet haben, bekommen wir auch eine Antwort. Die Rückgabe besteht aus Header und Body, getrennt durch eine leere Zeile.

Eine Antwort könnte zum Beispiel so aussehen:
HTTP/1.0 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Content-Type: text/html
Content-Length: 1354

<html>
<body>
<h1>Hallo Welt!</h1>
(mehr Inhalt)
</body>
</html>

Nun muss also je nach Anwendung der Header und Body getrennt werden. Lesen wir also so lange aus, bis der Header abgearbeitet ist, und brechen ab:
$header = "";

while(!feof($socket)) {
    $line = fgets($socket);

    if($line == "\n" || $line == "\r\n") {
        break;
    }

    $header .= $line;
}

Sobald die Zeile leer ist, wird das Lesen abgebrochen. Die Funktion feof() frägt ab, ob das Ende der auszulesenden Ressource erreicht ist und fgets() liest sie zeilenweise aus.

Nun muss der Body-Teil komplett gelesen werden:
$body = "";

while(!feof($socket)) {
    $line = fgets($socket);
    $body .= $line;
}
Und zum Schluss (bzw. auch schon früher) kann dann das Verarbeiten der Daten stattfinden.

In diesem Beispiel werde ich die Daten einfach ausgeben:
echo "Header:<br />";
echo "<pre>".$header."<pre>";

echo "Body:<br />";
echo "<pre>".$body."<pre>";


Gesamter Code (GET-Request)

Für diejenigen, die nicht gerne Codeschnipsel aus einem Artikel zusammensetzen wollen, habe ich den Code komplett zusammengefasst:
<?php
// Socket öffnen
$socket = fsockopen("tcp://91.121.116.185", 80, $errno, $errstr, 5);


// Request senden
$newLine = "\r\n";

$header  = "GET / HTTP/1.0".$newLine;
$header .= "Host: www.dennis-parsch.de".$newLine;
$header .= "User-Agent: ".$_SERVER['HTTP_USER_AGENT'].$newLine;
$header .= "Referer: http://www.adresse-vorher.de/".$newLine;
$header .= $newLine;

fwrite($socket, $header);


// Header lesen
$header = "";
while(!feof($socket)) {
    $line = fgets($socket);

    if($line == "\n" || $line == "\r\n") {
        break;
    }

    $header .= $line;
}


// Body lesen
$body = "";
while(!feof($socket)) {
    $line = fgets($socket);
    $body .= $line;
}


// Ausgabe
echo "Header:<br />";
echo "<pre>".$header."<pre>";

echo "Body:<br />";
echo "<pre>".$body."<pre>";
?>