Parsovanie stránky pomocou cURL

Published:

Add / read comments

Niekedy sa stáva, že je potrebné v nejakej aplikácii využiť aj dáta z inej webovej stránky. Napríklad získať aktuálnu hodnotu teploty a vlhkosti vzduchu a tieto potom spracovať a užívateľom zobraziť na svojich stránkach. Ja som raz potreboval spracovať stránku, kde je zoznam krajín a u každej krajiny bola informácia o počte obyvateľov, rozlohe, hustote atď.

Tieto informácie som potom potreboval využiť ďalej na vygenerovanie súboru vo formáte XML (ale o tom až ďalší článok). Nebudem písať žiadne definície čo je cURL, všetko podstatné nájdete na oficiálnych stránkach PHP tuto.

Idem priamo k veci, najprv treba dáta z danej stránky načítať do nejakej premennej:

$returned_page = get_data_from_url('http://www.geonames.org/statistics/');

Pričom na toto som si vytvoril funkciu, ktorej ako argument predám URL stránky, ktorú chcem vyparsovať:

function get_data_from_url($url) {

  // vytvori novy cURL zdroj
  $ch = curl_init();
  $timeout = 5;

  // nastavi moznosti cURL prenosu dat
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);

  // nastavi vracanie dat z URL do premennej a nie do browseru, pri neuspechu vrati FALSE
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  // uchopí URL a vloží ju do premennej 
  $data =curl_exec($ch);

  // zatvori cURL zdroj a vycisti systemove zdroje
  curl_close($ch);
  if($data){
    return $data;
  }else{
    $data = 'Nepodarilo sa stiahnut stranku!';
    return $data;                                         
  }
}

Po úspešnom získaní dát do premennej je možné dáta ďalej spracovať. Najprv je si potrebné preštudovať zdrojový kód stránky a zistiť akým spôsobom sú dáta usporiadané a zvoliť stratégiu, akou dáta zo stránky vyparsujeme. V mojom prípade som potreboval získať zoznam štátov a informácie o ich populácii, rozlohe a ich medzinárodný kód.

Zistil som, že pre na stránke je tabuľka so všetkými údajmi identifikovaná unikátnym identifikátorom "statistictable" a náležite som toho využil:

// vráti všetko od prvého výskytu identifikátora až po koniec
$table = stristr($returned_page,"statistictable");

Týmto som sa zbavil nepotrebným informácií z prednej časti stránky, potreboval som sa však zbaviť aj dát, ktoré nasledovali po tabuľke. Takže som si zistil pozíciu začiatku a konca tabuľky v reťazci a túto tabuľku som z reťazca vyrezal:

// pozícia začiatku tabulky
$pos_start = strripos($table,"statistictable");  
// pozícia konca tabuľky
$pos_end = strripos($table,"<tfoot>");
// vyrezanie tabuľky	
$subtable = substr($table, $pos_start, $pos_end);	 

Čiže teraz som mal pekný reťazec s dátami, ktoré som potreboval nejakým spôsobom odseparovať. Ideálna by bola štruktúra dvojrozmerného poľa, pričom riadky matice (poľa) predstavujú jednotlivé štáty a stĺpce matice obsahujú dáta o každom štáte. Bolo potrebné využiť regulárne výrazy, lebo každý riadok bol trošku odlišný.

//rozbijem tabulku do riadkov
$rows = preg_split("/&lt;tr\s?(class=\"odd\")?\>/", $subtable);
 
$cells = array();

//prechadzam kazdy riadok
foreach ($rows as $row){

  //rozbijem bunky z riadku do dvojrozmerneho pola
  $cells[] = preg_split("/<td\s?(class=\"rightalign\")?\>/", $row);

}	                    

Bohužial máme teraz v jednotlivých bunkách nielen dáta, ale aj nepotrebný kód okolo nich, ktorý predstavujú zvyšky tabuľky, ktorú sme rozbili. Je teda potrebné pole prejsť a nepotrebný kód odstrániť.

$i=0; $j=0; $bunky = array();

// osklbem z buniek tabulky nepotrebne tagy na ich konci
$krajina = array(); $i=0; 
  foreach($cells as $kluc => $pole){
    $j=0;
    foreach ($pole as $hodnota){
      $krajina=preg_split("/<\/td>/", $hodnota);

      $cells[$i][$j]=$krajina[0];
      $j++;
    }
    $i++;		
  }

Bolo potrebné sa aj zbaviť liniek, do ktorých bol zabalený názov krajiny. Čiže som prešiel opäť celé pole a na rad prišli opäť regulárne výrazy.

//upravy prvkov pola
for($i=0; $i<count($cells); $i++)
{
  for($j=0; $j<count($cells[$i]); $j++)
  {
    //teraz vyparsujem nazov krajiny z linku ktory je treti v poradi
    if($j==3){
 
      // regularny vyraz voci ktoremu porovnavam
      $regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";

      if(preg_match_all("/$regexp/siU", $cells[$i][$j], $matches, PREG_SET_ORDER)) {

	foreach($matches as $match) {    	
	  // $match[2] = adresa linky 
	  // $match[3] = text linky
	  $cells[$i][$j] = $match[3];
	}
      } 
    }
  }		
}				

Uvedený regulárny výraz je schopný vyparsovať aj krajinu, ktorej názov sa skladá z viacerých slov. Nakoniec som teda získal pekné dvojrozmerné pole s dátami o jednotlivých krajinách, ktoré môžem ďalej ľubovolne použiť.

Joj, takmer som zabudol! Je dôležité sa pozrieť, či máte vo vašej verzii PHP-čka skompilovanú knižnicu cURL a to tak, že si na serveri zbehnete nasledujúci skriptík:

<?php
echo "Sucasna PHP verzia: ".phpversion();

//Kompletne informacie o konfiguracnych nastaveniach serveru a preddefinovanych premennych systemu
echo phpinfo();
?>

Ak tam takú knižnicu nemáte, pochopiteľne Vám to nebude fungovať. Takže si nájdite súbor, ktorý sa nazýva "php.ini". Ten je umiestnený tam, kde máte nainštalované PHP. V tomto súbore si nájdite riadok, kde je napísane: ;extension=php_curl.dll a odstráňte tú bodkočiarku a reštartujte server (pravdepodobne máte Apache). Týmto ste si aktivovali knižnicu cURL.

Nezabudnite navštíviť nasledujúci článok, kde je pokračovanie pokračovanie problematiky spracovania získaných údajov. Celý kód z obidvoch článkov si môžete aj stiahnuť a otestovať sami.

Published:

Add / read comments

FIND ME

Share, follow or connect with me.