13. Kolovoz 2008.

Siniša na parsanju

Sinisa org Dugo nije bilo nekog programiranja ovdje. Što je ok, jer dosta je programiranja na radnom mjestu, di ću ga još ufuravat u slobodno vrijeme.

Ali dobro je s vremena na vrijeme napravit nekakav programerski post, čisto da pokažemo da znamo i možemo, jelda?

Daklem, na redu je parsanje i stvaranje RSS feeda iz jednog upitnog sajta: sinisa.org. Mamlaz je sad već ima dosta dugo promijenio lice i naličje tzv. bloga što je ok, napredak i promjene u društvu i tako to, ali bio je prelijen da stavi feed.

A kako su mu postovi sve više neumjereni, neuravnoteženi te ih stavlja u nepravilnim vremenskim odmacima pravi je zločin neimanje RSS podrške koja je danas obavezan sastojak svakog weba.

Zato je tu Lion's Fart čiji je gazda na godišnjem odmoru pa je imao vremena da odvoji nekoliko trenutaka za analizu Sinišinog HTML koda, izvlačenje nužnih podataka te izradu kratke PHP skripte koja će stvoriti RSS feed.

• • • • •

Pa da krenemo. (Potrebno je osnovno znanje PHPa.)

Ako zavirimo u source samog Trpanja bivamo ugodno iznenađeni: Siniša nam je olakšao posao lijepim formatiranjem koda. Svaki post izgleda ovako:

<div class="post">
<div class="title"><a href='/index.php?post=1234567890'>Naslov</a></div>
<div class="date"> utrpano prije xyz vremena.</div>
<div class="text">sadržaj</div>
</div>

Ovdje je sve što nam treba: link, naslov, datum i sadržaj. Sve što treba je zavrtit petlju, izvadit ove podatke i složit ih po redu u XML datoteku.

Idemo redom. Na početku stavimo cijeli html u array (liniju po liniju, to radi funkcija file().

$file = file('http://www.sinisa.org');

Nakon toga postavimo neke pizdarije da si olakšamo život. $output je array gdje ćemo stavljati postove.

$size = sizeof($file);
$output = array();
$counter = 0;
$i = 0;

Na redu je petlja, vrtimo liniju po liniju i tražimo početak posta.

while($i < $size)
{
if(strpos($file[$i], '<div class="post">') !== FALSE)
{

Ako je pronađen početak posta onda ulazimo u parsanje naslova koji se nalazi u slijedećoj liniji (i + 1):

$line = $file[$i + 1];
$search = "<a href='/index.php?post=";

$pos1 = strpos($line, $search) + strlen($search);
$pos2 = strpos($line, '</a>');

Vadimo link, tj. desetoznamenkasti (zato ovaj "10") broj:

$output[$counter]['link'] = substr($line, $pos1, 10);

A malo dalje od njega se nalazi naslov (12 je ovaj 10 plus završetak taga):

$output[$counter]['title'] = substr($line, $pos1 + 12, $pos2 - $pos1 - 12);

Slijedeća linija (ova u kojoj piše "utrpano prije xyz vremena") nam ne treba (datum ćemo izvadit na drugom mjestu), nego ona iza njega:

$line = $file[$i + 3];

Iz nje izvadimo sadržaj posta koji je iza određenog stringa:

$search = '<div class="text">';

$pos = strpos($line, $search) + strlen($search);
$len = strlen($line);

Sadržaj ide do kraja linije, ali moramo oduzeti 7 što je dužina </DIV> taga plus novi red:

$output[$counter]['text'] = substr($line, $pos, $len - $pos - 7);

I završavamo petlju. Na brojač dodajemo tri jer smo već isparsali iduća tri reda, a sve skupa prekidamo na 30 jer na toliko je seronja limitirao postove:

$counter++;
$i += 3;
}
$i++;
if($counter == 30) break;
}

Ovime smo u arrayu $output dobili vrijednosti link, title i text za svaki post.
Ostaje još da kreiramo sam feed, i to običan RSS 2.0. (Ovo je ujedno i primjer najjednostavnije moguće feed datoteke.)

Prvo zaglavlje:

header('Content-type: text/xml');
echo "<?xml version="1.0" encoding="UTF-8"?>n";

Onda zaglavlje XML datoteke:

<rss version="2.0">
<channel>
<title>sinisa.org</title>
<description>RSS za sinisa.org</description>
<link>http://www.sinisa.org</link>
<language>hr</language>
<generator>Lion's Fart</generator>

(Naravno, nismo propustili "potpisati" se negdje.)

I nakon toga u petlji provrtimo postove.

Funkcija strftime() pretvara unix_timestamp format u format koji zahtijeva feed.
(E, da, id-ovi postova su zapravo timestamp postanja, pa nam je i tu olakšan posao.)

<?
foreach($output as $line)
{
?>
<item>
<title><?= htmlspecialchars($line['title']) ?></title>
<description><?= htmlspecialchars($line['text']) ?></description>
<link>http://www.sinisa.org/index.php?post=<?= $line['link'] ?></link>
<pubDate><?= strftime("%a, %d %b %Y %T +0100", $line['link']) ?></pubDate>
</item>
<?
}
?>

(Funkcija htmlspecialchars() nam "korigira" specijalne znakove da se RSS readeri ne bune.)

I konačno kraj:

</channel>
</rss>

• • • • •

I to je sve. Kratko i onako školski, bez regularnih izraza i modernih parserskih trikova. Source je zazipan ovdje, a feed je tu.

Ako vam je bilo bar centimetar informativno dužni ste pivo. A Siniša je dužan pet jer je dobio feed.

PS. Znam da je source ponešto loše formatiran ali jebiga bit će ispravljeno u nekoj budućoj verziji bloga. ;)

Komentari

1 Favicon FilmTV 14.08.2008. 1:12

Vrlo lijepo i korisno! :)

2 Favicon cell 14.08.2008. 13:12

legendo...
siniši se napit krvi što nema rss...

3 Favicon d1a 14.08.2008. 13:17

ajde hvala kurcu

4 Favicon Sinisa Dukaric 14.08.2008. 13:50

Nemrem vjerovat da si to slozio i to za vrijeme godisnjeg! Maaaa, uf! :)
Pet piva velis? moze ;)

5 Favicon c0d3r_ 14.08.2008. 17:27

Siniša, sad moraš promjeniti sliku u headeru... Obrisat da nema RSS-a... hehe.
Lion , sad si sjebo koncepciju "trpanja"!!!

6 Favicon tomo 25.08.2008. 14:10

to se čekalo.

Dodaj komentar:

* Ime:

e-mail:

WWW:

* komentar:

Dozvoljeni tagovi su: <A>, <B>, <I>, <U> i <S>. E-mail adresa se nigdje neće prikazati.