Artikel im RSS Feeder verzögern

Welcher Blogger kennt das Problem nicht: man scheibt einen neuen Artikel, liest ihn vor dem veröffentlichen nochmals genau durch beseitigt alle Fehler, und stellt den Artikel danach ins Internet. Auf dem Blog noch kurzen eine Kontrolle, ob alles passt und Prompt findet man noch einen Fehler. Soweit so schlecht, den Fehler noch schnell beseitigen bevor es jemand sieht, das Internet ist ja Realtime. Fast; auf der Seite wird der Fehler nicht mehr angezeigt, dafür haben sich die Feedreader schon die alte und fehlerhafte Version gespeichert.
Dieses Problem kann man ganz einfach beheben. Entweder man machte keine Fehler mehr, oder man zeigt die neuen Artikel erst eine gewisse Zeit (zum Bsp 5 Min) später im RSS-Feed an. Dadurch hat man Zeit um die Fehler zu beheben, bevor die Feedreader überhaupt merken, dass es etwas neues gibt. In meinem Fall war das eine kleine Anpassung in der mySQL Abfrage.

Vorher:
<? mysql_query("... articleDate<".time()." ..."); ?>

Nachher:
<? mysql_query("... articleDate<".(time()-(5*60))." ..."); ?>


Nun hoffe, ich dass die Artikel in den Feedreader (und auch im Blog) etwas weniger Fehler haben.

RSS Feed mit SimplePie parsen

Ich beschäftige mich nun wieder etwas mehr mit dem Parsen von RSS mit PHP. Unter anderem weil ich mit dem Gedanken spiele einen RSS Aggregator für die Bikeblogs und/oder mir einen Lifestream zu bauen. Dafür eignet sich die Klasse SimplePie sehr gut. Im Gegensatz zu Magpie wird SimplePie etwas aktiver entwickelt.
hier nun mal ein kleines Beispiel, wie man die Daten aus einem RSS Feed ausliest. Wie gesagt ist das mit SimpePie recht einfach.
<?
// SimplePie einbinden
require_once("simplepie/simplepie.inc");

// Neues Objekt erstellen
$pie=new SimplePie;
?>

Nun hat man das SimplePie Objekt erstellt und kann jetzt angeben, welcher Feed geparst werden soll. Alternativ kann man die Feedurl, sowie angeben zum Cachingverhalten auch direkt im Konstruktor angeben. Ich verzichte hier aber darauf, da man bei einem Aggregator oder Lifestream mehrere RSS Dateien parsen muss, ohne jedes mal eine neues Objekt zu erstellen.
<?
// Feed Adresse setzen
$pie->set_feed_url($feed);

// Feed parsen
$pie->init();
?>

Mit der Methode init() wird der Feed nun geparst und man kann sich an das auslesen der Daten machen.
<?
// Anzahl der Elemente im Feed auslesen
$count=$pie->get_item_quantity();

// Jedes Element durchgehen
for($i=0;$i<$count;$i++)
{
    
// Daten auslesen
}
?>
So liest man zuerst die Anzahl der Elemente im Feed aus und geht alle nacheinander durch. Und schlussendlich muss man nur noch die Daten auslesen. Dies sieht so aus:
<?
// Ein "ItemObject" erstellen
$item=$pie->get_item($i);

// Titel
$title=$item->get_title();

// Inhalt
$content=$item->get_content();

// Link
$link=$item->get_link();

// Zeit als Unix Timestamp
$time=$item->get_date("U");
?>

Und alles zusammen sieht dann so aus:
<?
// SimplePie einbinden
require_once("simplepie/simplepie.inc");

// Neues Objekt erstellen
$pie=new SimplePie;

// Feed Adresse setzen
$pie->set_feed_url($feed);

// Feed parsen
$pie->init();

// Anzahl der Elemente im Feed auslesen
$count=$pie->get_item_quantity();

// Jedes Element durchgehen
for($i=0;$i<$count;$i++)
{
    
// Ein "ItemObject" erstellen
    
$item=$pie->get_item($i);

    
// Titel
    
$title=$item->get_title();

    
// Inhalt
    
$content=$item->get_content();

    
// Link
    
$link=$item->get_link();

    
// Zeit als Unix Timestamp
    
$time=$item->get_date("U");
}
?>

In der Api Reference werden alle Funktionen sehr schön und meistens mit einem Beispiel beschrieben.

Neue Feedfunktionalitäten

Heute habe ich einige funktionalitäten zum RSS Feed hinzugefügt. Neu kann man den Feed auch nur für eine bestimmtes Thema, einen Tag oder einen Ort abonieren. Die Adresse sieht fast gleich aus wie im Blog. Man muss nur das http://blog.t-error.ch durch das http://feeds.t-error.ch/blog/ ersetzten.
Bikeinteressierte dürften also an diesem, Panoramafanatiker an diesem und Savogninvernarrte an diesem Feed interessiert sein. Die Links zu den Feeds werde ich wohl zu den jeweiligen Seiten hinzufügen. Momentan muss man noch einwenig selbstständig sein, wenn man diese Funktionalität nutzen will.
Selbstverständlich darf man immer noch den Feed mit allen einträgen Benutzen. Aber vieleicht gibts ja Leute, die nur einem speziellen Thema interessiert sind.

Veränderungen auf der Seite

Nun hat es wieder einige Verbesserungen auf dieser Homepage gegeben:

Kommentare:
Dank einem Tipp vom Markus Baumi habe ich eine Funktion eingebaut, die anzeigt, welches Feld fehlt oder flasch ausgefüllt ist. Wird zum Beispiel die Rechnung falsch ausgefüllt so wird dieses Feld Rot dargestellt und der Kommentar wird nicht gespeichert.

Kontakt:
Neu hat diese Seite auch ein Kontaktformular. Wenn also jemand mit mir Kontakt aufnehmen will und dafür keinen Kommentar schreiben möchte, dann sich dort bei mir melden. Alle Felder mit Sternen müssen ausgefüllt werden, sonst geht nichts.

Vor einem Jahr:
Im Blog wird nun auf der linken Seite die Box "vor einem Jahr" angezeigt. Dort sollen schliesslich Beiträge, die vor einem Jahr geschrieben wurden erscheinen. Der nächste ist am 1. April fällig (kein Scherz)

Photolog:
Auch den Photolog habe ich einwenig verbessert. Dies ist allerdings schon länger her, aber wenn ich schon dabei bin. Es gibt nun eine Übersicht mit allen Photos. Und man kann auch auf das Bild klicken um zum nächsten zu gelangen.

Feed:
Der RSS Feed zeigt nun auch die GEO-Daten für einzelne Posts an. So kann man auf der Blogug Map auch die Posts verfolgen.

In Zukunft kommt sicher noch eine Trackbackfunktion. Diese habe ich schon zu lange aufgeschoben. Und wenn jemand noch Verbesserungsvoschläge hat, so werde ich sehen, was man dort machen kann.

Linktipps von del.icio.us mit PHP erstellen

Wie man schon einmal beobachten konnte, habe ich nun auch meine delicious Links in meinem Blog. Allerdings werden die Links nur jede Woche angezeigt. Dazu habe ich selber ein kleines Script geschrieben.
Das Script wird täglich durch einen Cronjob aufgerufen und liest die Links aus dem RSS Feed von delicious und schreibt sie in eine Datenbank. Dort werden sie aufbewahrt, bis sie von einem anderen Script ausgelesen und auf die Webseite geschreiben werden. Das passiert bei mir wöchentlich.

Für die Technik-Interessierten habe ich hier die Datenbankstruktur und den Code des Scriptes, welches die Links ausliest. Das schreiben der Links in den Blog sollte ja nicht so schwierig sein.
Bei Gelegenheit werde ich die Daten nicht mehr aus dem Feed, sondern aus der API nehmen. Aber so funktionierts ja auch.
Ach ja: Das Script verwendet MagpieRSS um die RSS Datei zu parsen.

Die Tabellenstruktur
mysql> describe delicious;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| delID          | int(11)      |      | PRI | NULL    | auto_increment |
| delTitle       | varchar(200) |      |     |         |                |
| delLink        | varchar(200) |      |     |         |                |
| delTags        | varchar(200) |      |     |         |                |
| delDescription | text         |      |     |         |                |
| delLang        | char(2)      |      |     |         |                |
| delDate        | int(11)      |      |     | 0       |                |
| delActive      | tinyint(4)   |      |     | 0       |                |
+----------------+--------------+------+-----+---------+----------------+
Wenn delActive auf 1 ist, bedeutet das, dass der Link schon auf der Homepage angezeigt wird.

Der PHP Code
#!/usr/bin/php
<?
// abstand machen, damits auch schoen aussieht
function space($lenght)
{
    
$count=100-$lenght;
    for(
$i=0;$i<$count;$i++)
    {
        echo 
" ";
    }
}

// alle klassen, funktionen usw einbinden
require_once("/home/t-error/public_html/includes/_head.inc.php");

// magpie einbinden
require("magpierss/rss_fetch.inc");

// rss daten herunterladen und parsen
$data=fetch_rss("http://del.icio.us/rss/blacklord");
$data=$data->items;

// los gehts
foreach($data AS $item)
{
    
// die daten in verstaendliche variabeln schreiben
    
$title=        addSlashes($item['title']);
    
$link=         $item['link'];
    
$date=         intVal($item['date_timestamp']);
    
    
// tags als array speichern
    
$tags=         explode(" ",strToLower($item['dc']['subject']));
    
$description=  NULL;

    
// wenn eine beschreibung geschreiben worden ist
    
if(isSet($item['description']))
    {
        
$description=addSlashes($item['description']);
    }

    
// den lang: tag rausfiltern und die richtige sprache in $lang schreiben
    
$tags_arr=array();
    foreach(
$tags AS $tag)
    {
        if(
preg_match("/^lang:([a-z]{2}$)/",$tag,$result))
        {
            
$lang=$result[1];
        }
        else
        {
            
$tags_arr[]=$tag;
        }
    }

    
// tags wieder zusammensetzten
    
$tags=implode(" ",$tags_arr);

    
// ueberpruefen, ob der link schon in der datenbank ist
    
$res=$db->query("
                SELECT
                    delActive
                FROM
                    "
.TBL_PREFIX.TBL_DELICIOUS."
                WHERE
                    delDate="
.$date." AND
                    delLink='"
.$link."'");

    
// wenn nein: einfuegen. los!
    
if($db->num_rows($res)==0)
    {
        
$db->query("
                INSERT INTO
                    "
.TBL_PREFIX.TBL_DELICIOUS."
                    (
                        `delTitle`,
                        `delLink`,
                        `delDate`,
                        `delTags`,
                        `delDescription`,
                        `delLang`
                    )
                VALUES
                    (
                        '"
.$title."',
                        '"
.$link."',
                        '"
.$date."',
                        '"
.$tags."',
                        '"
.$description."',
                        '"
.$lang."'
                    )"
);
                    
        
// noch eine kleine ausgabe
        
echo $title;
        
space(strLen($title));
        echo 
"[ inserted ]\n";
    }
    
    
// wenn ja: nur aendern, man weiss ja nie
    
else
    {
        if(
$db->result($res,0,"delActive")==0)
        {
            
$db->query("
                    UPDATE
                        "
.TBL_PREFIX.TBL_DELICIOUS."
                    SET
                        `delTitle`='"
.$title."',
                        `delLink`='"
.$link."',
                        `delDate`='"
.$date."',
                        `delTags`='"
.$tags."',
                        `delDescription`='"
.$description."',
                        `delLang`='"
.$lang."'
                    WHERE
                        delDate="
.$date." AND
                        delLink='"
.$link."'");
        }
    }
}
?>

Dieses Script kann, wenn die Zugriffsrechte korrekt gesetzt sind, über die Shell aufgerufen werden.

Verbesserungsvorschläge sind gerne Willkommen

RSS Feed

Ich habe jetzt mal einen RSS Feed für den Blog gebaut. Er ist noch lange nicht fertig, aber es ist valide und das ist ja mal das wichtigste.

Zu finden ist er unter http://feeds.t-error.ch/blog/

Bei gelegenheit werde ich noch einige Features wie Feeds nur für bestimmte Topics oder für den Photolog erstellen, aber für den Anfang sollte das mal reichen.