So schreiben Sie ein Script für XML-Sitemaps in PHP

Von am 14.01.2013

Mit den Sitemaps will Google die Indexierung von Websites erleichtern. Webmaster stellen dazu eine oder mehrere Sitemaps online und der Googlebot orientiert sich an deren Einträgen. Wie Sie Sitemaps mit PHP erzeugen, zeigt der folgende Beitrag

Der Googlebot an sich ist reichlich einfach gestrickt. Er startet auf einer Seite und arbeitet sich anhand der Links zu den nächsten Dokumenten vor. Die liest er ein, verfolgt die nächsten Links und macht so weiter, bis er die Seite durch hat. Das Problem dabei ist: Betreiber von dynamischen Sites können nicht sicher sein, ob Google wirklich alle Einträge der Datenbank einliest. Der Grund dafür kann in vergessenen oder falschen Links liegen. Oder die Einträge sind nur über eine Suchfunktion zu erreichen - und damit außer Reichweite für Suchmaschinen.

Sitemap in XML

Dieses Problem geht Google mit den Sitemaps an. Das sind Auflistungen aller Dateien einer Website in einem XML-Datenformat. In die Sitemap schreiben Sie die URLs Ihrer Web-Seiten und fügen, wenn Sie möchten Aktualisierungsdatum, Gewichtung und ein Aktualisierungsintervall hinzu. Ein Beispiel sieht so aus:

<?xml version="1.0" encod</code><code>ing="UTF-8"?>

  <urlset xmlns="http://www.google.com/schemas/sitemap/0.84">

   <url>

    <loc>http://www.meineseite.foo/</loc>

    <lastmod>2005-11-07</lastmod>

    <changefreq>monthly</changefreq>

    <priority>0.4</priority>

   </url>

  </urlset>

Die ersten beiden Zeilen müssen immer in der Sitemap stehen, ebenso die letzte Zeile. Dazwischen beginnt und endet jeder Eintrag mit <url>...</url>.

In <loc> steht die URL des Beitrags. Das Datum der letzten Aktualisierung in <lastmod> muss im ISO-Format 8601 (http://www.w3.org/TR/NOTE-datetime) vorliegen. In der Regel reicht hier eine Datumsangabe wie 2005-11-07. Falls Sie häufiger aktualisieren, fügen Sie die Zeit hinzu. Der Eintrag sähe dann so aus: 2005-07-05T10:28:19+00:00.

Der Parameter <changefreq> gibt an, wie oft sich der Inhalt der Seite ändert, etwa "always", "hourly", "daily", "weekly" oder "never". Die Priorität <prority> ist ein Wert zwischen 0 und 1. Die kümmert sich nur um die Gewichtung der Seiten innerhalb des eigenen Angebots. Sie können damit nicht das Ranking bei Google beeinflussen.

Alle Angaben sind lediglich Hinweise an den Googlebot. Sie können den Googlebot nicht mit einer Sitemap steuern oder manipulieren. Ebenso wenig ist es möglich, mit der Sitemap Dateien von der Indexierung auszuschließen. Hierfür gibt es die robots.txt.

Sitemap mit PHP erzeugen

Bleibt die Frage: wie erzeugt man eine Sitemap, wenn man ein paar Tausend Dokumente auf dem Server hat. Antwort: das erledigt PHP. Die im folgenden vorgestellte Klasse googleSitemap() nimmt in einem Array die Informationen über URLs und Zusatzinformationen entgegen und gibt einfach eine Sitemap aus. Der Vorteil: bei jedem Abruf von Google erzeugt das Programm eine aktuelle Sitemap. So sind Sie sicher, dass nichts verloren geht.

Später brauchen Sie nur noch den Namen des PHP-Programms an Google zu übermitteln, fertig. Dabei ist es übrigens kein Problem, wenn die Datei nicht auf "XML" endet. Wichtig sind für Google nur die erhaltenen Daten.

Um die im folgenden vorgestellte Klasse verwenden zu können, müssen Sie herausfinden, wie Sie an die URLs und Änderungsdaten der auf Ihrem Server enthaltenen Artikel kommen. Diese Informationen schreiben Sie in ein assoziatives Array, das wie folgt strukturiert ist:

array('loc' => [Dateiname],

'lastmod' => [Datum],

'priority' => [Priorität 0-1],

'changefreq' => [Aktualisierungsfrequenz])

 

Die Schlüssel enthalten bereits die Namen der für die Sitemap notwendigen Elemente. Der Schlüssel loc ist verbindlich. Fehlt er, meldet die Sitemap-Klasse einen Fehler. Alle weiteren Angaben sind optional. Leere Einträge ignoriert die Klasse.

Die Datumsangabe verlangt Google zwar im Format ISO 8601. Aber darum brauchen Sie sich nicht zu kümmern. Übergeben Sie das Datum so, wie Sie es haben. Die Klasse versucht, es in das richtige Format umzuwandeln. Zuständig hierfür ist die Funktion strtotime(), die unterschiedlichste Arten von Datumsangaben versteht. Welche genau das sind, können Sie unter http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html nachlesen. Im Schlüssel priority geben Sie einen Wert zwischen 0 und 1 ein, also 0.1 oder 0.7. Falls Sie keine Angabe machen, gilt der Standardwert von 0.5. Die changefreq erwartet einen der folgenden Textstrings: always, hourly, daily, weekly, montly, yearly oder never. Auch diese Angaben sind nur Hinweise an Googlebot, an die der Bot nicht gebunden ist.

Ist das Array fertig, können Sie es an die Sitemap-Klasse übergeben. Dazu erzeugen Sie zunächst ein neues Sitemap-Objekt mit

$oSitemap = new googleSitemap('http://foo.bar/');

 

Als Parameter verlangt der Konstruktor die Basis-URL. An diese URL werden später alle Einträge angehängt. Achten Sie darauf, dass am Ende des Domain-Namen ein Schrägstrich stehen muss. Fehlt der, erzeugt die Sitemap-Klasse einen Fehler.

Danach fügen Sie Ihr Array mit der Methode addEntry() zur Sitemap hinzu. addEntry() verlangt als Parameter das Array. Sie können entweder eine vorbereitete Array-Variable übergeben, etwa mit

$arrSomeEntry = array('loc' => 'testfile.php?id=2765&cid=10580',

'lastmod' => '2003-02-24 23:38:54',

'priority' => '0.4',

'changefreq' => 'never');

$oSitemap->addEntry($arrSomeEntry);

 

Oder Sie schreiben das Array direkt in den Aufruf der Methode:

$oSitemap->addEntry(

array('loc' => 'welcome.php?i=52&j=1',

'lastmod' => '2005-11-04 12:10',

'priotity' => ''));

 

Sind alle Daten an die Sitemap übergeben, starten Sie die Ausgabe. In diesem Fall geht das mit

echo $oSitemap->generateSitemap();

direkt an den Client. Sie können die Daten aber genauso gut in eine Variable übergeben oder direkt in einer Datei speichern.

In der Datei sitemap.php auf der Heft-CD finden Sie ein paar Beispiele, wie Sie die Klasse nutzen können.

Die Klasse dahinter

Für das Erzeugen der Sitemap ist die Klasse googleSitemap zuständig.

Der Konstruktor kümmert sich zunächst einmal um die übergebene Basis-URL:

if (!preg_match("/^https?:\/\/[a-z]([a-z0-9-.]+)+?.[a-z]+\/$/i", $strBaseURL))

 

Ein regulärer Ausdruck untersucht die übergebene URL auf syntaktische Richtigkeit. Sie achtet darauf, dass das erste Zeichen der URL ein Buchstabe ist, lässt danach beliebig viele Folgen aus Buchstaben, Bindestrichen und Punkten zu und verlangt zum Schluss ausschließlich Zeichen für die Top-Level-Domain sowie einen Schrägstrich. Das i am Schluss des Regulären Ausdrucks schaltet die Unterscheidung zwischen Groß- und Kleinschreibung ab.

Der Prüfausdruck ist noch nicht perfekt. Er lässt zum Beispiel Domain-Namen wie http://www.-bla.com/ zu. Aber in erster Linie soll er sich ja um den abschließenden / kümmern.

Falls die Basis-URL korrekt ist, landet sie in der Objektvariablen $this->strBaseUrl. Falls nicht, erzeugt

trigger_error("URL {$strBaseURL} not valid. Must be http[s]://[some.]domain.ext/", E_USER_ERROR);

 

eine Fehlermeldung.

Die Methode addEntry() übernimmt das beim Aufruf übergebene Array. Danach sieht sie nach, ob das Array den Schlüssel loc hat

if (array_key_exists('loc', $arrEntry))

Ist das der Fall schleust addEntry die URL durch die Funktion htmlspecialchars(). Die wandelt Zeichen wie & und < in die von Google geforderten Entities um. Ohne diese Umwandlung wäre der Sitemap-Code nicht wohlgeformt und würde eine Fehlermeldung verursachen.

Findet addEntry keinen Schlüssel mit der Bezeichnung loc, kommt es zu einer Fehlermeldung. Denn loc ist von Google verbindlich vorgeschrieben. Alle anderen Schlüssel sind optional und werden nicht überprüft.

Damit ein eventuell übergebenes Datum ins richtige Format kommt, wird es zuerst durch mit der Funktion strtotime() in einen Timestamp umgebaut und dann mit gmdate() im von Google gewünschten ISO-8601-Format ausgegeben. Falls Sie PHP 5 benutzen, können Sie übrigens den Formatierungs-Parameter 'Y-m-d\TH:i:s+00:00' in gmdate() mit 'c' ersetzen.

Sind die Änderungen erledigt, übernimmt das Array $arrSitemapEntries die übergebenen Daten.

Um die Ausgabe schließlich kümmert sich schließlich generateSitemap(). Sie bereitet das XML-Gerüst für die Sitemap vor und arbeitet sich dann durch das Array $arrSitemapEntries. Die einzelnen Einträge erzeugt der Generator aus den Schlüsseln des Arrays. Damit kein unerwünschtes Element in der Sitemap landet, gleicht

if (in_array($strKey, $this->arrValidElements))

 

den Schlüssel noch mit dem Array ab, das die erlaubten Schlüssel enthält. Ist dies nicht der Fall, wird der Eintrag ignoriert und eine entsprechende Fehlermeldung ausgegeben.

Sind alle Einträge abgearbeitet, geht die fertige Sitemap zurück an das aufrufende Programm.

Sitemap validieren

Bevor Sie Ihre Sitemap bei Google anmelden, sollten Sie sie überprüfen. Ob die fertige Sitemap mit dem Google-Sitemap-Schema übereinstimmt, prüfen Sie unter http://schneegans.de/sv/. Hier geben Sie unter Validate by URL die URL Ihrer Sitemap ein und klicken auf Validate. Die anderen, notwendigen Informationen holt sich der Server automatisch.

Falls Sie Ihr Sitemap-Programm zunächst nur auf einem lokalen, nicht per Internet erreichbaren Server ausprobieren wollen, rufen Sie Ihr PHP-Sitemap-Programm lokal per Browser auf. Dann wechseln Sie in die Quelltextansicht und speichern die XML-Sitemap als Datei. Diese Datei laden Sie unter Validate by file upload auf den Server und klicken auf Validate.

Um Bandbreite zu sparen und den Server nicht zu überlasten, sollten Sie die Validierung anhand von ein paar Testeinträgen durchführen.

Der Schneegans-Server prüft die XML-Daten übrigens auch auf Wohlgeformtheit. Syntax-Fehler in den Sitemaps fallen damit auch auf – zum Beispiel vergessene &-Zeichen. Ist Ihre Sitemap korrekt, erscheint die Meldung Validated as: Google Sitemap. Die Meldung No supported document type declaration was found ignorieren Sie.

Sitemap bei Google anmelden

Bevor Sie Ihre Sitemap bei Google unterbringen können, müssen Sie sich zunächst anmelden. Dazu rufen Sie

https://www.google.com/webmasters/sitemaps/login

Falls Sie bereits ein Google-Konto besitzen, etwa für Google Mail oder Google Groups, verwenden Sie dieses um sich anzumelden. Haben Sie noch keinen Google-Zugang, wählen Sie Google Konto erstellen und holen sich einen kostenfreien Zugang. Nach dem Anmelden geht es weiter mit Sitemap hinzufügen. Unten im Fenster geben Sie die Adresse der Sitemap ein – inklusive dem vorangestellten http://. Nach URL senden sehen Sie die Sitemap-Hauptseite wieder. In der Liste steht nun Ihre Domain, der Name der Sitemap und der Status Ausstehend. Jetzt heißt es erst einmal warten. Nach ein paar Stunden sollte Google die Sitemap aufgenommen haben.

Crawling überprüfen

Mit Hilfe der Google Sitemaps-Seite prüfen Sie auch, ob der Googlebot beim Crawlen Ihrer Seite auf Probleme gestoßen ist. Dazu klicken Sie einfach auf überprüfen neben dem Namen der zu prüfenden Seite. Google bittet Sie danach, zunächst eine Kontrolldatei im Root-Verzeichnis der zu überprüfenden Site zu erzeugen.

Den Dateinamen sehen Sie fett gedruckt auf der Seite. Erzeugen Sie eine leere Datei mit diesem Namen und laden Sie diese per FTP auf den Server. Falls Sie Shell-Zugriff auf Ihre Site haben, geben Sie ein

touch GOOGLEab123456789xyz.html

Achten Sie darauf, dass alle diese Datei lesen dürfen. Das geht mit

chmod o+r GOOGLEab123456789xyz.html

Ist die Datei da, geht es weiter in den Sitemaps. Klicken Sie auf Status überprüfen und kurz danach erscheint die Meldung Überprüft. Anschließend dürfen Sie einen Blick auf die Crawling-Statistiken Ihres Servers werfen. Sie werden dort eine Liste von Dateien finden, auf die Googlebot in den letzten Tagen nicht zugreifen konnte, sei es wegen der robots.txt oder wegen eines Fehlers. Es lohnt sich, diese Statistik mindestens einmal pro Woche anzusehen, um Problemen mit dem Google-Suchindex vorzubeugen.

 

googleSitemap.class.php

<?php

/**

* Erzeugt eine Google Sitemap und gibt sie direkt aus

*

* @author Martin Goldmann <martin@goldmann.de>

*/

class googleSitemap

{

var $arrSitemapEntries = array();

var $strBaseURL = '';

var $arrValidElements = array('loc','lastmod','changefreq','priority');


/**

  * Konstruktor - verlangt URL mit / am Schluss!

  *

  * @param str $strBaseURL

  * @return googleSitemap

  * @todo Regexp zum Prüfen der Domain ausbauen

  */

function googleSitemap($strBaseURL)

{

  if (!preg_match("/^https?:\/\/[a-z]([a-z0-9-.]+)+?.[a-z]+\/$/i", $strBaseURL))

  {

   trigger_error("URL {$strBaseURL} not valid. Must be http[s]://[some.]domain.ext/", E_USER_ERROR);

  }

  else

  {

   $this->strBaseURL = $strBaseURL;

  }

}


/**

  * Fügt Eintrag zur Sitemap hinzu

  *

  * @param array $arrEntry

  */

function addEntry($arrEntry)

{

  if (array_key_exists('loc', $arrEntry))

  {

   $arrEntry['loc'] = $this->strBaseURL.htmlspecialchars($arrEntry['loc']);

  }

  else

  {

   trigger_error('Key \'loc\' missing', E_USER_ERROR);

  }

  if (array_key_exists('lastmod', $arrEntry))

  {

   $arrEntry['lastmod'] = gmdate('Y-m-d\TH:i:s+00:00', strtotime($arrEntry['lastmod']));

  }

  $this->arrSitemapEntries[] = $arrEntry;

}


/**

  * Bereitet Sitemap auf und gibt sie zurück

  * @return array

  */

function generateSitemap()

{

  $strSitemap = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";

  $strSitemap .= "<urlset xmlns=\"http://www.google.com/schemas/sitemap/0.84\">\n";

  

  foreach ($this->arrSitemapEntries as $arrEntry)

  {

    $strSitemap .= "<url>\n";

    foreach ($arrEntry as $strKey => $strValue)

    {

     if (in_array($strKey, $this->arrValidElements))

      $strSitemap .= "<{$strKey}>".$strValue."</{$strKey}>\n";

     else

      trigger_error("Element {$strKey} ignored", E_USER_NOTICE);

    }

    $strSitemap .= "</url>\n";

  }

  $strSitemap .= "</urlset>";

  return $strSitemap;

}

}

?>

 

(erschienen 2006 in Internet Professionell)

Aktualisiert am: 14.01.2013
Dateien
googleSitemap.class.zip


Ihr Kommentar:


Name:



wie wäre es einfach so:
preg_match("/^https?:\/\/(www\.|)[a-z]([a-z0-9-.]+)+.[a-z]+\/$/i",
$strBaseURL)
Damit sollte das Problem mit www.-bla behoben sein. Und wenn man mal
bedenkt, dass der Artikel 2006 erschienen ist, ist das ne ziemlich
gefährliche Abfrage, weil es bis vor kurzem (Ende 2009) gar keine 2
bzw. einstelligen Domainnamen gab.
[Lars | 05.02.2010] Antworten