A legújabb írásunkban egy RSS 2.0 kiolvasót mutatunk be nektek, amellyel akár saját honlapotokra készíthettek más oldalakról átszívott hírekkel teli blokkot. Lássunk tehát hozzá.
A program alapja a myRSSParser class, amely kimondottan RSS 2.0 forrásokra lett megírva. Ebből adódóan hiába próbálunk beleadni más forrásokat valószínűleg hibákat fogunk kapni. A program alapvetően rémesen egyszerű. Először is szükségünk van egy Parser-re, amely a kapott RSS forrást darabokra szedi. Ennek a kódja így fest:
class myRSSParser
{
# keeps track of current and preceding elements
var $tags = array();
# array containing all feed data
var $output = array();
# return value for display functions
var $retval = "";
# constructor for new object
function myRSSParser($file)
{
# instantiate xml-parser and assign event handlers
$xml_parser = xml_parser_create("");
xml_set_object($xml_parser, $this);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "parseData");
# open file for reading and send data to xml-parser
$fp = @fopen($file, "r") or die("myRSSParser: Could not open $file for input");
while($data = fread($fp, 4096)) {
xml_parse($xml_parser, $data, feof($fp)) or die(
sprintf("myRSSParser: Error %s at line %d ",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser))
);
}
fclose($fp);
# dismiss xml parser
xml_parser_free($xml_parser);
}
function startElement($parser, $tagname, $attrs=array())
{
# RSS 2.0 - ENCLOSURE
if($tagname == "ENCLOSURE" && $attrs) {
$this->startElement($parser, "ENCLOSURE");
foreach($attrs as $attr => $attrval) {
$this->startElement($parser, $attr);
$this->parseData($parser, $attrval);
$this->endElement($parser, $attr);
}
$this->endElement($parser, "ENCLOSURE");
}
# check if this element can contain others - list may be edited
if(preg_match("/^(RDF|RSS|CHANNEL|IMAGE|ITEM)/", $tagname)) {
if($this->tags) {
$depth = count($this->tags);
list($parent, $num) = each($tmp = end($this->tags));
if($parent) $this->tags[$depth-1][$parent][$tagname]++;
}
array_push($this->tags, array($tagname => array()));
} else {
if(!preg_match("/^(A|B|I)$/", $tagname)) {
# add tag to tags array
array_push($this->tags, $tagname);
}
}
}
function endElement($parser, $tagname)
{
if(!preg_match("/^(A|B|I)$/", $tagname)) {
# remove tag from tags array
array_pop($this->tags);
}
}
function parseData($parser, $data)
{
# return if data contains no text
if(!trim($data)) return;
$evalcode = "\$this->output";
foreach($this->tags as $tag) {
if(is_array($tag)) {
list($tagname, $indexes) = each($tag);
$evalcode .= "[\"$tagname\"]";
if(${$tagname}) $evalcode .= "[" . (${$tagname} - 1) . "]";
if($indexes) extract($indexes);
} else {
if(preg_match("/^([A-Z]+):([A-Z]+)$/", $tag, $matches)) {
$evalcode .= "[\"$matches[1]\"][\"$matches[2]\"]";
} else {
$evalcode .= "[\"$tag\"]";
}
}
}
eval("$evalcode = $evalcode . '" . addslashes($data) . "';");
}
# display a single channel as HTML
function display_channel($data, $limit)
{
extract($data);
if($IMAGE) {
# display channel image(s)
foreach($IMAGE as $image) $this->display_image($image);
}
if($TITLE) {
# display channel information
$this->retval .= "
\n\n";
}
}
function fixEncoding($input, $output_encoding)
{
if(!function_exists('mb_detect_encoding')) return $input;
$encoding = mb_detect_encoding($input);
switch($encoding) {
case 'ASCII':
case $output_encoding:
return $input;
case '':
return mb_convert_encoding($input, $output_encoding);
default:
return mb_convert_encoding($input, $output_encoding, $encoding);
}
}
# display entire feed as HTML
function getOutput($limit=false, $output_encoding='UTF-8')
{
$this->retval = "";
$start_tag = key($this->output);
switch($start_tag) {
case "RSS":
# new format - channel contains all
foreach($this->output[$start_tag]["CHANNEL"] as $channel) {
$this->display_channel($channel, $limit);
}
break;
case "RDF:RDF":
# old format - channel and items are separate
if(isset($this->output[$start_tag]['IMAGE'])) {
foreach($this->output[$start_tag]['IMAGE'] as $image) {
$this->display_image($image);
}
}
foreach($this->output[$start_tag]['CHANNEL'] as $channel) {
$this->display_channel($channel, $limit);
}
foreach($this->output[$start_tag]['ITEM'] as $item) {
$this->display_item($item, $start_tag);
}
break;
case "HTML":
die("Error: cannot parse HTML document as RSS");
default:
die("Error: unrecognized start tag '$start_tag' in getOutput()");
}
return $this->fixEncoding($this->retval, $output_encoding);
}
# return raw data as array
function getRawOutput($output_encoding='UTF-8')
{
return $this->fixEncoding($this->output, $output_encoding);
}
}
Miután ezt felmásoltuk a szerverre jön maga a fájl, amely kiiratja az RSS hírforrást. Ebben a fájlban végezhetünk el különböző beállításokat értelemszerűen értelmezve a következő változókat: $FEEDURL - Ez az RSS címe pl.: http://www.sg.hu/plain/rss.xml $NUMITEMS - mennyi bejegyzést akarunk kilistázni $TIMEFORMAT - a dátum milyen formában jelenjen meg. $CACHEFILE - a letárolt tartalmat hova mentse a program (erre azért van szükség, hogy ne minden oldatelöltéskor szedjük le az RSS-t, mert az belassítaná a rendszert, hanem megadott időközönként frissítsünk csak) $CACHETIME - milyen időközönként kapcsolódjon fel az RSS-re és szedje le az új bejegyzéseket.
Ennyit kell gyakorlatilag tudni a beállításokhoz most pedig lássuk a magát a kódot:
header('Content-Type: text/html; charset=utf-8');
# define script parameters
$FEEDURL = "http://www.sg.hu/plain/rss.xml";
$NUMITEMS = 20;
$TIMEFORMAT = "Y. F j., h:i";
$CACHEFILE = "/tmp/" . md5($FEEDURL);
$CACHETIME = 1; # hours
# download the feed iff a cached version is missing or too old
if(!file_exists($CACHEFILE) || ((time() - filemtime($CACHEFILE)) > 3600 * $CACHETIME)) {
if($feed_contents = @file_get_contents($FEEDURL)) {
# write feed contents to cache file
$fp = fopen($CACHEFILE, 'w');
fwrite($fp, $feed_contents);
fclose($fp);
}
}
include "rss.parser.php";
$rss_parser = new myRSSParser($CACHEFILE);
# read feed data from cache file
$feeddata = $rss_parser->getRawOutput();
extract($feeddata['RSS']['CHANNEL'][0], EXTR_PREFIX_ALL, 'rss');
# display leading image
if(isset($rss_IMAGE[0]) && $rss_IMAGE[0]) {
extract($rss_IMAGE[0], EXTR_PREFIX_ALL, 'img');
echo "
A php 27. sorától kezdve lehet szépítgetni a megjelenítést. A program, ha képet tlaál az RSS-ben az automatikusan kirakja, ezen felül kiírja az RSS címét a bejegyzések címeit leírásait és dátumát is.
Milyen megoldást javasolsz, ha több rss forrásból is szeretnék kiíratni. Saját magamnak szeretnék egy olyan honlapot, amelyen az általam olvasott hírportálok hírei jelennének meg, ehhez viszont több hírforrást is fel kellene vennem.
Üdv.:
Petyka
BullsEye
2011/10/26 17:36
Nekme megy rendesen ahoyg leírtátok. Vendég: szerintem nincs tmp mappád vagy nicns rá joga írni a scriptnek. Oda tárolja a cache fájljait.
Üdv
Vendég
2010/11/09 18:03
nekem az alábbi hibát dobja:
Could not open tmp/cache7ab125854ae6430474c573c1f9f4eaef for input
Cégünk által készített weblapokat eddig ennyien látták:
45 285 389
ebből a mai napon 27 647 látogató volt
Miért a TotalStudio?
Nálunk Ön az első Az Ön elképzelései és a mi kreativitásunk illetve szaktudásunk a garancia arra, hogy honlapja vagy grafikai megjelenése olyan legyen amilyenre mindig is vágyott.
Több éves tapasztalat Cégünk munkatársai több mint kilenc éve foglalkoznak webfejlesztéssel, informatikával és szerverüzemeltetéssel, ezen idő alatt mindenre felkészültünk!
Verhetetlen minőség Munkánkban nem ismerünk kompromisszumot! Mindig a legmagasabb minőségre törekszünk. A magunkkal szemben támasztott maximalizmus és a legújabb technológiák használata garantálja, ügyfeleink elégedettségét.
Gyorsaság és megbízhatóság Nálunk nem kell heteket várni, hiszen honlapja akár öt munkanapon belül is elkészülhet a szerződés aláírásától, de a gyorsaság soha nem megy a minőség rovására!