A 108.hu-ra kelett egy modult készítenem, amely összegyűjti a bhakta blogok legfrisebb bejegyzéseit. Ilyesmit csinál a blogroll, vagy a hírekkel a hírkereső. Többféle megoldást is kipróbáltam, melyekből ez bizonyult a leghasználhatóbbnak. Az eljárás egyszerű, de nagyszerű.Előszőr azzal próbálkoztam, hogy amikor a user megnyitja az oldalt, akkor egy sima
fopen
szépen végignyitogatja a vizsgálandó oldalakat és beolvassa ezekről a szükséges (mondjuk a legfrisebb) adatokat. Ezzel az volt a baj, hogy már 3 különböző oldalnál az oldal letöltését drasztikusan lecsökkentette. Megnéztem különböző variációkat ezen az alapon (fsockopen, fopen, curl, join(file), file_get_contents) de így mind lassú volt. Ekkor úgy gondoltam, hogy el lehetne menteni egy állapotot egy szövegfileba, amit aztán bizonyos időközönként (pl 2 óránként) lehetne frissíteni.
Ehhez a következő 3 alkotóelemet kellett összerakni:
- írni egy függvényt, ami végiglátogatja az oldalakat, kiveszi belőlük az áhított tartalmat és beleírja egy szövegfileba
- létrehozni egy
cron
feladatot ami a fenti scriptet lefuttatja bizonyos időközönként - írni egy másik függvényt ami a szövegfileból beolvassa az adatokat és megjeleníti az oldalon
Az oldallátogató függvény
#!/usr/local/bin/php <?php function frissblog($webcim,$cim,$keres,$cserelminta, $tobbsor=false){ /* A megadott $webcimmel kapcsolatba lép megkeresi a $keres kifejezést, ha ebben a sorban nincs link akkor hozzáadja, a $cserelminta mintára illeszkedő részt kiveszi a sorból, a $tobbsor true esetén ezt több mint egy soron keresztül folytatja */ $kimenet .= "nt".'<li>'; $fp = fopen("http://".$webcim."/", "r"); if (!$fp){ $kimenet .= $webcim . ' (nem elérhető)'; } else{ $kilep = $megvan = false; while(!feof($fp) && !$kilep){ /*keressük meg az első bejegyzést (sort) ami illik $keres mintára*/ if(strpos($sor=fgets($fp),$keres) !== false || $megvan){ //ha van linkje távolítsuk el az esetleg ott megbúvó stílus definíciót, style vagy class $sor = preg_replace("/style="[^"]*"/",'',$sor); $sor = preg_replace("/class="[^"]*"/",'',$sor); //ha több soron keresztül kerestünk és elértük a végét if($tobbsor && $megvan){ $kimenet .= preg_replace("/$cserelminta/",'',$sor); $kilep = true; } //többsoros, de még nem értük el a végét elseif($tobbsor){ $kimenet .= preg_replace("/$cserelminta/",'',$sor); } //nem többsoros elseif(!$tobbsor){ $kimenet .= preg_replace("/$cserelminta/",'',$sor); $kilep = true; } $megvan = true; } } //ha nincs benne link adjuk hozzá if(strpos($kimenet,'<a href') === false) $kimenet = '<a href="http://'.$webcim.'">' . $kimenet . '</a>'; $kimenet .= ' <span class="blogcim">('.$cim.') </span></li>'; //gyomláljuk ki az esetleg bekerült -ket $kimenet = str_replace(' ','',$kimenet); fclose($fp); } return($kimenet); } //--------------------------------------------------------- $kimenet .= '<ul>'; $kimenet .= frissblog('krisnamosolya.blogter.hu','Krisna mosolya','<h1>','</*h1[^>]*>'); $kimenet .= frissblog('lal.freeblog.hu','Egy krisnás szerzetes naplója','<div class="bejegyzescim">','</*[^>]*>',true); $kimenet .= '</ul>'; $fp = fopen(ALAPKONYVTAR.'moduls/blog.txt','w'); fwrite($fp,$kimenet . "n"); fclose($fp); ?>
Az első sor #!/usr/local/bin/php
tudja a parserrel, hogy a kis php programunk nem normál böngészőn keresztül futtatott program, hanem egy parancssori program. Ezt a formátumot kell használnunk ha olyan php programokat írunk, amelyeket parancssorból akarunk futtatni. Az elérési út a php futtatható állományára kell mutasson.
A függvényünk fopen
-nel megnyitja a kért webcímet és az ott talált filet (ami várhatóan az index.php vagy index.html) elkezdi soronként végignézni. Ha megtalálja benne a keresett mintát akkor azt tisztítja, szükség esetén hozzáadja a linket, hozzáadja a hivatkozó szöveget és az így összerakott stringet adja vissza visszatérési értékként.
Ezután a különböző blogokra meghívjuk a függvényt a megfelelő paraméterekkel. A mintákat úgy találtam ki, hogy ellátogattam az oldalakra és a forrásfileban megnéztem, hogy hogy néznek ki a legfrisebb bejegyzések.
Végül pedig fwrite
-tal beleírjuk az egészet a szövegfileunkba. Ezt a filet jó előtte a php számára írhatóvá tenni, és a jogait futtathatóra állítani, máskülönben egyrészt nem fog működni, másrészt meg eltöltünk egy csomó időt azzal, hogy megpróbáljuk kitalálni, hogy miért nem. Ha feltesszük a programocskát a szerverre és meghívjuk a kedvenc böngészőnkkel, akkor az első sort fogja kiírni csupán. Ha ezen felül még kiír valamit akkor nézegessük meg mert nagy eséllyel hibaüzenetek lesznek. A betöltendő oldalak számától függően akár 1-2 percig is eltarthat míg lefut.
A cron
A cron
démon a linux rendszerek egyik alapvető eleme, hacsak valami érthetelen oknál fogva nem Windows fut a webszerverünkön, akkor biztosan ott lesz a démonok között. A probléma annyi, hogy általában sima felhasználóknak nincs joga egy webszerveren cron feladatokat létrehozni, de gondolom a szolgáltatók nagy részének nincs különösebb kifogása egy ilyen aranyos kis cron task futtatása ellen.
Előszőr létre kell hoznunk egy szövegfilet, ami az alábbi formátumban kell legyen:
10 */2 * * * /home/rrd/public_html/108/blog.php
Az első szám azt jelzi, hogy a parancsot melyik percben, a második, hogy melyik órában, aztán melyik napon, melyik hónapban, és a hét melyik napján kell lefuttatni. Ha valamelyik szám helyén * van akkor azt jelenti, hogy minden. Azaz a mi esetünkben minden második órában az óra 10. percében kell lefuttatnia a fenti elérési úton lévő blog.php filet. Tovább nem magyarázom, akit érdekel az keressen rá a crontab-ra, magyarul is sok leírás található.
Ha esetleg adminisztrációs hozzáférésünk van a szerverhez, akkor lehet, hogy az adminisztrációs programunkban van olyan rész ahol crontab taskokat lehet kezelni. A DirectAdmin például ilyen. Ha nincs akkor valahogy rá kell vennünk a webszerver üzemeltetőjét, hogy életet leheljen a crontab fileunkba. Ha van ssh hozzáférésünk akkor meg mi magunk is meg tudjuk csinálni.
A megjelenítő függvény
if($_SESSION['blog']) print $_SESSION['blog']; else{ $fp = @fopen("./moduls/blog.txt", "r"); if (!$fp){ print 'Nem elérhető'; } else{ while(!feof($fp)){ $kimenet .= fgets($fp); } fclose($fp); } $_SESSION['blog'] = $kimenet; print $_SESSION['blog']; }
Semmi érdekes. Megvizsgálom, hogy létezik-e már a sessionben a blog bejegyzés, ha nem akkor beolvasom a blog.php által generált fileból. Ez azért kell mert elvileg a sessionban szereplő adatokhoz gyorsabban hozzáfér a php mint ha minden oldalletöltésnél a filet kellene nyitogálnia. Ezután meg fogjuk és egyszerűen kiírjuk a sessionból a tartalmat.
Ennyi az egész és kész!