Artikel im Internet unter http://www.hidemail.de/blog/google-sitemaps---script-zur-erstellung-einer-sitemap-datei-fuer-google.shtml.
Donnerstag, 6.12.2007, 17:25:53 Uhr

Google Sitemaps - Script zur Erstellung einer Sitemap-Datei für Google


Googles Sitemaps sollen helfen, daß einzelne Webseiten von Google auch dann gefunden werden, wenn sie nirgends verlinkt sind. Dies ist dann wichtig, wenn man häufig wechselnden Content hat und ältere Beiträge nicht verloren gehen sollen. Zudem verspricht Google, daß die Indizierung dann schneller erfolgt.
Was liegt also näher, als sich ein kleines Perl-Script zu schreiben, das eine solche Sitemap erzeugt, und zwar direkt auf dem Server?

Also machte ich mich mal ran an das Problem, und zwar mit folgenden Vorgaben:
- Leicht zu konfigurieren
- findet alle Dateien auf dem Server
- Angabe von Ordnern, auf Wunsch inkl. Unterordner
- korrekte Angabe von Umlauten und Sonderzeichen

Also hab ich mal folgendes Script geschrieben

#!/usr/bin/perl

print <<EOF;
Content-Type: text/html\n\n
<HTML>\n<HEAD>\n
<Title>Sitemapper for Google</Title>
</HEAD>
<Body>
EOF

#############
# Parameters
#############

my $domain='http://www.hidemail.de'; # Your domain without ending /
my $to_root='../';# Path to your HTDOCS-Root with ending /
my $filename='sitemap.xml';# Sitemap-File
my $folders='test';# Processed folders, separated by ,
# If you want to include subfolders, place a +before the foldername, for example '+sites'

my $filetypes='.htm.html.txt.php.shtml';# Filetypes


###############
# End of Params
###############
use CGI::Carp "fatalsToBrowser";
use URI::Escape qw(uri_escape_utf8);

$folders=~ s/\, +/\,/g;
my @folders=split(',',$folders);
my %files=();

foreach (@folders){
my $include_subdirs=0;
if (substr($_,0,1) eq '+'){$include_subdirs=1; $_=~ s/^\+//;}

@files=get_all_files("$to_root$_",$include_subdirs,$filetypes);
foreach my $file (@files) {
$file=~ s/\/\.\//\//;
$time=(stat($file))[9];
$file=~ s/^$to_root/$domain\//;
$files{$file}=$time;
}
}
print qq~<b>Processing Files</b><br>\n~;
open (my $sitemap,">",$to_root.$filename) || die ("Can not create Sitemap-File");

print $sitemap <<EOF;
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84
http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">
EOF


foreach (keys %files){print qq~$_<br>\n~;
my ($Sekunde, $Minute, $Stunde, $Tag, $Monat, $Jahr) = localtime($files{$_});
$Monat++;
$Jahr+=1900;
$Tag="0$Tag" if (length($Tag)==1);
$Monat="0$Monat" if (length($Monat)==1);
$Sekunde="0$Sekunde" if (length($Sekunde)==1);
$Minute="0$Minute" if (length($Minute)==1);
$Stunde="0$Stunde" if (length($Stunde)==1);
my $datum="$Jahr-$Monat-$Tag"."T";
my $zeit="$Stunde:$Minute:$Sekunde";
$_=~ s/</\<\;/g;
$_=~ s/>/\>\;/g;
$_=~ s/\&/\&\;/g;
$_=~ s/\'/\'\;/g;
$_=~ s/\"/\"\;/g;

$_=uri_escape_utf8($_,"\x00-\x1f\x7f-\xff" );
print $sitemap <<EOF;

<url><loc>$_</loc><lastmod>$datum$zeit+00:00</lastmod></url>
EOF

}

print $sitemap "</urlset>";
close $sitemap;

print "ready";

exit;


###################
# Parameter
# 0: Startdir ohne abschließendes /, aktuelles Verzeichnis = .
# 1: Unterverzeichnisse durchsuchen? 1: ja, 0: nein
# 2: Dateitypen in form .txt.htm.html , also direkt hintereinander, aber nur wenn nötig
#
# Neues Feature:
# Es kann ab sofort auch ein hash erzeugt werden, der als keys den Dateinamen mit Ordner usw. hat UND als Value den Dateinamen selbst
# 3: Nur kompletten Dateinamen oder Hash mit kompletten Dateiname und Dateinamen allein : 0 oder 1
# ansonsten wird alles gezeigt
#
# Einbindung per
# require 'lib.pl';
#
#
# Aufruf per:
#
# @dateien=get_all_files('c:/htdocs/',1,'.shtml.htm.txt');
#
# oder
#
# %dateien=get_all_files('c:/htdocs/',1,'.shtml.htm.txt',1);
#
# Autor: Peter Baumann
# Dieses Script darf bei Nennung des Autors frei verwendet werden
#############################################
sub get_all_files{

my $startdir=shift;
my $include_subdirs=shift;
my $endings=shift;
my $extendet=shift;

my %endings=();
$endings=~ s/\s//g;
my @endings=split('\.',$endings);
shift @endings;

my $endings=0;
$startdir=~ s/\/$//;

if (@endings != 0){
$endings=1; # wenn Endungen angegeben
foreach (@endings){
$endings{$_}=1;
}
}
@endings=();

my @dateien=();
push (my @all_directories,$startdir);

foreach my $akdir(@all_directories){

opendir (my $IN,$akdir);
my @all=readdir($IN);
closedir $IN;

foreach my $akdatei (@all){ next if ($akdatei eq '..' || $akdatei eq '.');
if (-d "$akdir/$akdatei") {
if ($include_subdirs == 1){
push (@all_directories,"$akdir/$akdatei");
next;
}
} else {
if ($endings==0){
push (@dateien,"$akdir/$akdatei");
push (@dateien,$akdatei) if ($extendet == 1);
}
else
{
my $lastpoint=rindex($akdatei,".");
next if $lastpoint == -1; # Keine Dateiendung gefunden

my $endung=substr($akdatei,$lastpoint+1-length($akdatei));

if ($endings{$endung} == 1){
push (@dateien,"$akdir/$akdatei");
push (@dateien,$akdatei) if ($extendet == 1);
}
}
}
}
}
return @dateien;
}



Naja, hier gibts die Version zum herunterladen...
Und wie funktioniert das nun?
Öffnen Sie die Datei mit einem Editor und edieren Sie die Parameter:
my $domain='http://www.ihredomain.de'; # Your domain without ending /
my $to_root='../';# Path to your HTDOCS-Root with ending /
my $filename='sitemap.xml';# Sitemap-File
my $folders='test';

Die $domain ist Ihre Domain, ohne abschließendes /.
$to_root gibt an, wo das Hauptverzeichnis liegt, in dem die zu durchsuchenden Seiten liegen, also im Normalfall '../'.
$filename ist der Dateiname der Sitemap, die später im HTML-Root angelegt wird.
$folder sind schließlich die Ordner, die durchsucht werden sollen, getrennt durch ein Komma. Sollen unterordner durchsucht werden, wird dem Ordnernamen ein + vorangestellt.
Will man das gesamte Document-Root, also die Ebene, in der die index.html oder .php oder shtml oder was auch immer liegt, so kann man '+./' angeben. Dann werden auch alle Unterverzeichnisse eingelesen. Aber wirklich ALLE!

Bringen Sie das Script in Ihren cgi-bin-Ordner und setzen Sie die Rechte auf 0755.

Der Aufruf erfolgt per: http://www.ihredomain.de/cgi-bin/sm.pl. Die Sitemap wird erzeugt.

Und wie funktioniert das Script?
Nun, das Script nutzt die Routine get_all_files, die ich hier schonmal vorgestellt habe. Es werden also alle Dateien mit der richtigen Endung gefunden.Anschließend werden die Daten der letzten Änderung gesucht und als passende Zeichenfolge in die Sitemap-Dateien geschrieben. Wichtig ist vorher, daß Umlaute wie ä ö ü codiert werden, und zwar nach Unicode. Sonst schimpft Google... Das macht die Zeile $_=uri_escape_utf8($_,"\x00-\x1f\x7f-\xff" );, die wirklich nur Sonderzeichen umwandelt, nicht aber / oder _-Zeichen.

Ich hoffe, das kleine Script gefällt...

Die Originalbeschreibung zu den Sitemaps gibt es hier zu lesen.
Übrigens
Wie man in der Dokumentation sehen kann, gibt es noch die Optionen changefreq und priority. Diese Optionen werden von diesem Script nicht unterstützt.

Genauso ist es nicht möglich, einzelne Dateien auszuschließen, wenn sie nicht indiziert werden sollen.


Artikel im Internet unter http://www.hidemail.de/blog/google-sitemaps---script-zur-erstellung-einer-sitemap-datei-fuer-google.shtml.