Aus dem Maschinenraum: Backup aller verlinkten Quellen aller WordPress Artikel

Wie bei Blogs üblich verlinken Horst und ich unsere Quellen. Für uns stellt sich die Frage, was passiert, wenn diese Quellen abgeschaltet oder verändert werden? Ein Backup des Stands bei der Erstellung eines Artikels ist sinnvoll.

Das soll möglichst automatisch und unabhängig vom redaktionellen Prozess erfolgen, der online innerhalb der WordPress-Seite selbst erfolgt.

WordPress bietet unter Meine Website / Einstellungen / Export / Alles Exportieren die Möglichkeit den Inhalt der Seite als XML zu exportieren. Dieses XML enthält – unter Anderem – die Texte aller Artikel und Seiten dieser WordPress-Seite.

Ich habe ein Perl-Skript (für die Unix-Kommandozeile) geschrieben, welches diese XML-Datei einliest, die Links verfolgt und lokal abspeichert.

Dieses Skript hat folgende Features:

  • Ablage aller Quellen eines Artikels in ein Verzeichnis pro Artikel.
    • Alle diese Verzeichnisse werden in einem voreingestellten Verzeichnis abgelegt.
  • Bereits gesicherte Artikel werden nicht erneut gesichert.
  • Gesichert werden nur die Webseiten, die im Artikel selbst verlinkt werden. Andere Links, die auf der von WordPress dargestellten Seite vorkommen, z. B. zu WordPress.com, werden nicht verfolgt.
  • Nur externe Links werden gesichert, d. h. Links auf eigene Artikel werden nicht mit gespeichert.
  • Die XML-Datei wird ebenfalls als Backup in das Zielverzeichnis gesichert. An der Originalstelle (bei mir ein allgemeines Download-Verzeichnis) kann die Datei bei Gelegenheit gelöscht werden.

Damit das Script richtig funktionieren kann, müssen bei der Erstellung von Artikeln ein paar Regeln bei der Verkinkung eingehalten werden:

  • Immer direkt auf die Quelle verlinken, nicht auf „eine Seite davor“.
  • Bei Quellen, die über mehrere Seiten verteilt sind muss auf eine Komplettansicht verlinkt werden. Falls das bei der Quelle nicht möglich ist, muss jede Seite (aus der zitiert wird) einzeln verlinkt werden.

Da die Funktion auf dem XML-Backup-File von wordpress.com basiert, gelten folgende Annahmen:

  • Das XML-File selbst ist das Backup der Artikel, die Texte sind vollständig enthalten.
  • Bilder, die in die Artikel eingebunden werden, gibt es bereits als lokale Kopie. Sie werden nicht erneut mit gesichert.

(Noch) fehlende Features:

  • Backup von Online Videos, z.B. youtube.
  • Die Zip-Datei von WordPress muss zunächst entpackt werden.
  • Fehlerbehebung und Korrektur sind unterentwickelt.
    • Bei Abbruch bleiben unvollständige Verzeichnisse zurück. Das wird beim nächsten Lauf nicht erkannt, so dass für diesen Artikel die Quellen nicht vollständig gesichert werden.
      • Der Nutzer muss das Verzeichnis nach Programmabbruch manuell löschen. Dann behebt ein neuer Programmlauf das Problem.
    • Fehlkonfiguration wird nicht verhindert.

Macht Ihr euch Gedanken über die Sicherung Eurer Quellen?

Gibt es bereits gute WordPress-Backup-Lösungen, die ich nicht kenne?

Kennt jemand eine bessere Möglichkeit Code hochzuladen und zu verlinken? Als Dokument konnte ich es nicht bei wordpress.com hochladen, also musste ich es als Text einbinden.

Anbei mein Code:

#!/usr/bin/perl -w

use strict;
use File::Copy;
use Cwd;
use HTML::TokeParser::Simple;

require XML::LibXML;

#Configuration
#-------------

my $BASEDIR="/home/foobar/Backup/references"; # The base directory for backup directory.

#Global variables
#-----------------

my $XML; # The xml wordpress backup file (input file for this program).

my $backupDirectory=""; # Backup location.

my $oldWorkingDirectory; # For saving the original working directory.

#Functions
#---------

sub usage(){
#precondition: $backupDirectory must be set
print <<EOF;
Usage
-----
$0 <wordpress_backup_xml_file>
Downloads all references from wordpress articles in
$backupDirectory
This program works incremental. Only new references are downloaded and stored.
The input file is copied to the destination directory.
EOF
}

# Main program
#-------------
select (STDOUT); $|=1; #flush!
$backupDirectory = $BASEDIR;

$oldWorkingDirectory = cwd();

$XML=shift;
if (!defined $XML)
{
usage();
print "\n\nError--> <wordpress_backup_xml_file> must be given ... exiting\n";
exit;
}

if (! -e $XML)
{
usage();
print "\n\nError--> $XML not found ... exiting\n";
exit;
}

if (! -d $backupDirectory)
{
mkdir $backupDirectory or die "\n\nError--> Unable to create backup directory: $!";
print "Backup directory created: $backupDirectory\n";
}

print "Parsing input file $XML\n";

my $xmlparser = XML::LibXML->new() or die "\n\nError--> Unable to create XML parser: $!";

my $dom = $xmlparser->parse_file($XML) or die "\n\nError--> Input file not a valid XML file: $!";

chdir $backupDirectory;

# extract main URL to distinguish between internal and external links
my $main_url;
foreach my $urls ($dom->findnodes("/rss/channel/link/text()"))
{
$main_url = $urls->toString();
last;
}

foreach my $items ($dom->findnodes("/rss/channel/item"))
{

my $url = $items->findvalue("./link");
my $postname = $items->findvalue("./wp:post_name");
my $post_type = $items->findvalue("./wp:post_type");
my $content = $items->findvalue("./content:encoded");
my $post_status = $items->findvalue("./wp:status");

if ((lc($post_type) eq "page")|| (lc($post_type) eq "post"))
{

if ( (!defined $postname) || ($postname eq "") || ($postname =~ /^\s*$/))
{ # Last condition checks for white space only string.
print "\n\nSkipping supposed article draft (WHITE SPACE NAME): $url\n";
next;
}

if (-d $postname)
{
print "\n\nReference backup for $postname already exists...skipping\n";
next;
}

print "\n\nDownloading references for URL: $url to $postname...\n";

my $htmlparser = HTML::TokeParser::Simple->new(\$content);
while (my $anchor = $htmlparser->get_tag('a'))
{
next unless defined(my $href = $anchor->get_attr('href'));

if (index (lc($href), lc($main_url)) == -1)
{
print "\t$href\n";

system ("wget", "-e robots=off", "-P$postname", "-EqkpH", $href);
}
else
{
print "\tSKIPPING (internal link) $href\n";
}
}
print "Done.\n";

} else
{
print "\n\nSkipping URL of post_type: $post_type ($url)...\n";
}
}

chdir $oldWorkingDirectory;

print "Copying $XML to backup directory...";
copy ($XML, $backupDirectory) or die "\n\nError--> Copy failed: $!";
print "done\n";

 

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s