81 látogatás.

Hírfolyamok feldolgozása

Pepita

2013-08-05 09:28:01

Cikk képManapság sok olyan magyar weblapot látunk, ami rendelkezik hírcsatornával, ezeket viszont kevés felhasználó olvassa, használja. Pedig hasznosak a hírfolyamok, ha nem az átlag internetezőknek, akkor nekünk, fejlesztőknek, mikor más oldalakról akarunk bizonyos tartalmakat kölcsönözni (mint itt is, a jobb sávban).

Ez a cikkem is megjelent a Weblaboron, itt egy kicsit kevesebb kódidézettel közöljük, mivel a teljes forráskód letölthető.

Léteznek egymással kapcsolatban lévő intézmények (klubok, egyesületek stb.), melyek szívesen megosztanák egymással híreiket, programajánlójukat, egyebet. (Régebben divat volt az időjárás is.) Ezt legegyszerűbben úgy lehet megvalósítani, ha feldolgozzák egymás hírforrásait. Igen, de milyen a jó feldolgozó? Igényeim a következők voltak:

  • A lehető legtöbb hírfolyamtípust képes legyen feldolgozni,
  • mégis egységes eredményhalmazt adjon vissza, használata során lehetőleg egyáltalán ne kelljen a formátummal foglalkozni;
  • szűrje a tartalmat beállítások szerint (pl. képek, egyes HTML elemek);
  • ha akarom, rendezze az elemeket dátum szerint csökkenő sorrendbe;
  • a dátumokat magyarul, a hét napjaival jelenítse meg;
  • rövidítsen a túl hosszú bevezetőkön, a benne esetleg szereplő HTML elemek helyes lezárásával;
  • lehetőleg egyszerűbb PHP függvényeket használjon, a minél jobb hordozhatóság érdekében.

Nos, olyan feldolgozót nem találtam, ami mindezt tudná, ezért fogtam a fejszét és belevágtam.

A legnagyobb feladatnak a különböző szabványok szerint készült XML dokumentumok egységes struktúrába rendezése látszott, ezért először jó sokat olvastam róluk a Wikipédián és különböző RFC-k között. Számomra úgy tűnik, hogy az RSS 2.0 a legelterjedtebb szabvány, ezért az egységesített struktúra és a változók nevei többnyire ezt követik.

class Rss_reader

A konstruktor mindössze beállítja az időzónát (ha PHP >= 5.1.0), ellenőrzi az mbstring kiterjesztés meglétét (az UTF-8 kódolás miatt szükséges), létrehoz egy DomDocument objektumot, és egyes változókat alaphelyzetbe állít. Ha valami hiba történik – itt és a többi függvénynél is – arról az errors tömbben olvashatunk (magyarul).

require_once('rss_reader.php');
$rss = new rss_reader();
if ($rss->errors <> '') {
    print_r($rss->errors);
}

Ezután következhet a feed betöltése

  • fájlból: $rss->load_file($filename), ha a tartalmat időzítve (cron) mentjük egy könyvtárunkba;
  • XML string-ből: $rss->load_xml($xml), ha a tartalmat egy változóba mentettük előzőleg;
  • közvetlenül URL-ből: $rss->load_url($url), ha rábízzuk a reader-re a távoli nyitást (ehhez allow_url_fopen – nek bekapcsolva kell lennie).

Mindhárom függvény false-al tér vissza sikertelenség esetén, ilyenkor az errors tömböt érdemes megnézni a fent említett módon. Sikeres betöltés (return true;) után meghívódik a belső read() függvény, ami a gyökérelem tagName tulajdonsága alapján eldönti, hogy a dokumentum RSS, RDF vagy Atom típusú, és meghívja az ennek megfelelő feldolgozót (read_rss(), read_rdf(), read_atom()).

Ekkortól a teljes feed hírtartalma elérhető az items tömbön keresztül, ennek elemei:

  • index: az elem sorszáma;
  • title: az elem címe;
  • link: az elem eredeti forrására mutató hivatkozás;
  • pubDate: az elem publikált dátuma magyarul (pl. 2011-12-15 Csütörtök, 19:20:58);
  • author: az elem szerzője (sok esetben üres string, egyébként név, de akár e-mail is lehet!);
  • description: az elem leírása (maga a hír), ez sok esetben HTML tag-eket is tartalmaz;
  • comments: ha vannak az elemhez tartozó hozzászólások, akkor arra mutató link. (Pl. a Weblabor feed-jébe az új fórumtémák kerülnek így.)

Egyéb változók, függvények az osztályban:

  • title: a hírcsatorna címe;
  • link: általában a forráshonlap főoldalára mutató link, ritkábban egy aloldalé vagy a feed-é;
  • description: a csatorna – közös – leírása, sok esetben üres;
  • lastBuildDate: elvileg a feed utolsó „összerakásának” az ideje (ez is magyar dátum, mint items-ben);
  • pubDate: csatorna közzétételének ideje (sok esetben csak egyik dátumot „hozza” a feed, ilyenkor a két változó azonos értékű);
  • ttl: a csatorna ajánlott frissítési ciklusideje (sec.), sokszor nincs (vagy rosszul van) megadva, jobb, ha mi döntjük el a feldolgozás gyakoriságát;
  • rsort_date(): Fordított (pubDate) sorrendbe rendezi az items tömböt;
  • getItemcount(): visszaadja a feed elemeinek számát;
  • errors: az esetleges hibaüzenetek tömbje.

A feed betöltése után, ha nem minden elemet akarunk megjeleníteni, javaslom az rsort_date() függvény használatát, ezután - a példa kedvéért – írjunk ki maximum 5 elemet, 150 karakter maximális hosszal:

$rss->rsort_date();
if ($rss->getItemcount() > 5) {
    $m = 5;
} else {
    $m = $rss->getItemcount();
}
for ($n=0; $n < $m; $n++) {
    echo('<div class="feed_item">');
    echo('<h3><a href="' . $rss->items[$n]['link'] .
         '">' . $rss->items[$n]['title'] .
         '</a></h3>'); 
    echo('<p><strong>' . $rss->items[$n]['author'] . ' </strong> ' .
         $rss->items[$n]['pubDate'] . '</p>');
    echo($rss->getSortText($n, 150, '<p><i><b><span><strong>'));
    if ($rss->items[$n]['comments'] > '') {
        echo('<p><a href="' . $rss->items[$n]['comments'] . '">Hozzászólások</a></p>');
    }
    echo("</div>\r\n");
}

Megjegyzem: feed megjelenítésekor illik kiírni a csatorna címét, leírását, linkjét is. Természetesen egészen más formátumban is megjeleníthetjük a tartalmat, itt a getSortText() függvényre térek ki részletesen, ami egy elem description–ét rövidítve, átformálva adja vissza.

Paraméterei:

  • itemIndex: elemkijelölő, ennek description–ét fogja használni;
  • length: a kívánt hossz karakterben;
  • allowTags: megengedett HTML tag-ek, ezek maradhatnak a description–ben, a többit kiveszi (ha 'all'-t adunk meg, mindent benthagy).

A length hosszt közelítésekkel keresi a függvény, ebbe nem számítanak bele a tag-ek, de a szóköz, stb. igen; az esetleges entitások, speciális karakterek miatt lehet némi eltérés (kb. 5-12 karakter) a megadott és a tényleges (hasznos) hossz között. Ha a rövidítendő description rövidebb length-nél, akkor nem történik levágás. Egyébként a szöveg szóvégnél lesz elvágva, a függvény pótolja a szükséges záró tag-eket, a szöveg végéhez pedig …-t fűz. A tag-ek számolásához és zárásához a private $tags1 és private $tags2 belső tömböket használja, ezeket bárki kiegészítheti szükség szerint. (Én kb. 30 db., különböző helyről származó feed-del teszteltem, sikerrel.)

Fontos tudni:

A hírcsatornák felhasználása nem mindig ingyenes! Minden esetben alaposan járjunk utána, hogy az adott oldal hírcsatornáját milyen feltételekkel használhatjuk fel! Ha az XML dokumentum forrásában nem találunk copyrigth információt, még nem jelenti azt, hogy szabadon felhasználhatjuk. Érdeklődjünk a honlap üzemeltetőjénél!

Egyes honlapok nem követik azt az ajánlást, miszerint egy hírcsatornába maximum 20 elemet mentsenek, és a teljes XML dokumentum mérete ne haladja meg a 300 kB-ot. Ez az osztály az egész dokumentumot egyszerre tölti be, ezért a nagyobb méretű feed-ek feldolgozása lassú lehet, extrém esetben memóriafoglalási hibát is idézhet elő. (A letölthető csomagban van egy méretesebb XML is, 900 elemmel.)

Egyebek:

Az osztály forráskódja az Rss_writer-el és a használatot bemutató egyszerű kóddal, info.txt-kel együtt tölthető le. A csomagban található XML dokumentumok csak a tesztelést szolgálják, nyilvános megjelenítésükhöz a létrehozó honlapok üzemeltetőinek engedélye szükséges (egyébként sem friss feed-ek).

Célom egy működőképes, az én igényeimet kielégítő osztály készítése és annak bemutatása volt, remélem, hogy másoknak is hasznára válik.

Horváth Péter


Nincsenek megjegyzések.