Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: waluty z NBP
Forum PHP.pl > Forum > Gotowe rozwiązania > Algorytmy, klasy, funkcje
stanik_jr
Witam,
poszukiwałem klasy do obsługi XML'a z kursami walut z NBP i w końcu napisałem sam, może komuś się przyda

  1. <?php
  2. /**
  3.  * Pobieranie kursów walut z NBP
  4.  * 
  5.  * Klasa do obsługi plików xml z kursami walut udostępnianych przez NBP
  6.  * 
  7.  * @author Bartłomiej Staniszczak <b_staniszczak at tlen dot pl>
  8.  * @copyright 2007 Bartłomiej Staniszczak
  9.  * @version 1.0
  10.  *
  11.  */
  12. class WalutyNBP {
  13.  
  14. /**
  15.  * Tablica z wszystkimi kursami zczytanymi z XML
  16.  *
  17.  * @var array
  18.  */
  19. private $arrKursy = array();
  20.  
  21. /**
  22.  * Zmienna zawierająca datę aktualizacji kursów
  23.  *
  24.  * @var string
  25.  */
  26. private $strData;
  27.  
  28. /**
  29.  * Konstruktor parsuje xml'a do tablicy
  30.  *
  31.  * @param string $strEncoding
  32.  * @param string $strUrlXml
  33.  */
  34. public function __construct($strEncoding='UTF-8',$strUrlXml='http://www.nbp.pl/Kursy/xml/'){
  35. $strUrlXml=$strUrlXml.$this->aktualny_xml().'.xml';
  36. $objXml = new XMLReader();
  37. if(function_exists('curl_init')){
  38. $objXml->XML($this->ccurl_fopen($strUrlXml));
  39. }
  40. else{
  41. $objXml->open($strUrlXml);
  42. }
  43. $j=0;
  44. while($objXml->read()){
  45. if($objXml->name === 'data_publikacji' && $objXml->nodeType==1){
  46. $objXml->read();
  47. $this->strData=$objXml->value;
  48. }
  49. if($objXml->depth==3){
  50. if($j==4){
  51. $j=0;
  52. $this -> arrKursy[$arrWaluta[2]]=$arrWaluta;
  53. $arrWaluta=array();
  54. }
  55. if($strEncoding!='ISO-8859-2'){
  56. $arrWaluta[$j]=iconv('ISO-8859-2',$strEncoding,$objXml->value);
  57. }
  58. else{
  59. $arrWaluta[$j]=$objXml->value;
  60. }
  61. $j++;
  62. }
  63. }
  64. }
  65.  
  66. /**
  67.  * Otwieranie pliku
  68.  * 
  69.  * Metoda otwiera plik i zwraca jego zawartość
  70.  *
  71.  * @param string $strUrl
  72.  * @return mixed
  73.  */
  74. private function ccurl_fopen ($strUrl){
  75. $strUser_agent = "Mozilla/8.0 (Windows 2008 SP32 + 3patch)";
  76. $resCh = curl_init();
  77. curl_setopt ($resCh, CURLOPT_URL, $strUrl);
  78. curl_setopt ($resCh, CURLOPT_USERAGENT, $strUser_agent);
  79. curl_setopt ($resCh, CURLOPT_COOKIEJAR, "cookie.txt");
  80. curl_setopt ($resCh, CURLOPT_HEADER, 0);
  81. curl_setopt ($resCh, CURLOPT_RETURNTRANSFER, 1);
  82. curl_setopt ($resCh, CURLOPT_FOLLOWLOCATION, 1);
  83. curl_setopt ($resCh, CURLOPT_TIMEOUT, 120);
  84. $mixResult = curl_exec ($resCh);
  85. curl_close($resCh);
  86. return $mixResult;
  87. }
  88.  
  89. /**
  90.  * Aktualna nazwa pliku XML z danymi
  91.  *
  92.  * @param string $strTabela
  93.  * @return string
  94.  */
  95. private function aktualny_xml($strTabela='a'){
  96. if(function_exists('curl_init')){
  97. $resLista = $this->ccurl_fopen('http://www.nbp.pl//Kursy/xml/dir.txt');
  98. $arrPlikiXML = explode("n",$resLista);
  99. }
  100. elseif(!function_exists('fsockopen') || !function_exists('fputs') || !function_exists('feof') || !function_exists('fgets')){
  101. $resPolalczenie = fsockopen ( "www.nbp.pl", 80 );
  102. $strHeaders = 'GET /Kursy/xml/dir.txt HTTP/1.0' . "rn"; 
  103. $strHeaders .= 'Host: www.nbp.pl' . "rn";
  104. $strHeaders .= 'User-Agent: Mozilla/8.0 (Windows; U; Windows NT 5.1; pl-PL; rv:1.7.10) Gecko/20050717 Firefox/1.0.6' . "rnrn";
  105.  
  106. fputs ( $resPolalczenie, $strHeaders );
  107. while ( ! feof ( $resPolalczenie ) ) {
  108. $arrPlikiXML[] = fgets ( $resPolalczenie, 128 ); 
  109. }
  110. fclose ( $resPolalczenie );
  111. }
  112. $arrPlikiXML = array_reverse ($arrPlikiXML);
  113. for($i=0; $i<=3; $i++){
  114. $strNazwa=trim($arrPlikiXML[$i]);
  115. if(substr($strNazwa,0,1)==$strTabela){
  116. $strDzisiejszyXML=trim($arrPlikiXML[$i]);
  117. }
  118. }
  119. return $strDzisiejszyXML;
  120. }
  121.  
  122. /**
  123.  * Zwraca wybrane waluty
  124.  * 
  125.  * Metoda zwraca informacje o podanych w parametrze walutach
  126.  *
  127.  * @param mixed $mixWaluty
  128.  * @return array
  129.  */
  130. public function zwroc_waluty($mixWaluty=array()){
  131. if(is_array($mixWaluty) && count($mixWaluty)==0){
  132. return $this->arrKursy;
  133. }
  134. elseif(!is_array($mixWaluty)){
  135. if(array_key_exists($mixWaluty,$this->arrKursy))
  136. return $this->arrKursy[$mixWaluty];
  137. return FALSE;
  138. }
  139. else{
  140. foreach($this->arrKursy AS $strKlucz => $arrWartosc){
  141. if(in_array($strKlucz,$mixWaluty))
  142. $arrWynikowa[$strKlucz]=$this->arrKursy[$strKlucz];
  143. }
  144. if(count($arrWynikowa)>0) 
  145. return $arrWynikowa;
  146. return FALSE;
  147. }
  148. return FALSE;
  149. }
  150.  
  151. /**
  152.  * Data aktualizacji kursów
  153.  *
  154.  * @return string
  155.  */
  156. public function getData(){
  157. return $this->strData;
  158. }
  159.  
  160. }
  161. ?>


przykładowe użycie:

  1. <?php
  2. $kursy = new WalutyNBP();
  3. $waluta = $kursy -> zwroc_waluty('USD');
  4. print_r($waluta);
  5. ?>


wynik:

Cytat
Array ( [0] => dolar amerykański [1] => 1 [2] => USD [3] => 2,8020 )


  1. <?php
  2. $kursy = new WalutyNBP();
  3. $waluta = $kursy -> zwroc_waluty(array('USD','PLN','EUR'));
  4. echo $kursy->getData().'<br/>';
  5. print_r($waluta);
  6. ?>


wynik:

Cytat
2007-05-22
Array ( [USD] => Array ( [0] => dolar amerykański [1] => 1 [2] => USD [3] => 2,8020 ) [EUR] => Array ( [0] => euro [1] => 1 [2] => EUR [3] => 3,7735 ) )
Sokal
A to tak można bez pozwolenia wykorzystywać dane banków? O.o
kwiateusz
zapewne tak, zwłaszcza że udostępniają jeszcze xmlki z danymi
arborea
No pewnie, że można korzystać - ja wrzucam co tylko mogę z http://www.money.pl/webmaster/ bo sami zrobili parę tabelek do wrzucenia na sajty, są też i aktualne kursy walut z wykresikiem smile.gif Teraz szukam czegoś z turystyki smile.gif
phpion
Odświeżam topic.
Czy pobierał ktoś z Was kursy z PKO BP? Konkretnie chodzi mi o tą tabelę:
http://www.pkobp.pl/index.php/id=waluty/zone=-1/section=ogol
Nie wiecie poza tym czy PKO BP udostępnia gdzieś xml z kursami? Ja nie namierzyłem niczego takiego, a do pobierania danych ze stron zaufania nie mam :/ Wystarczy, że coś się zmieni w kodzie i regexp może paść...
Pozdrawiam: pion

PS: muszę skorzystać z PKO BP bo Klient twierdzi, że jest tam najwyższy kurs Euro smile.gif więc przejście na NBP (gdzie kurs jest niższy) nie wchodzi w grę -> strata kasy
webmasts
wywala mi taki błąd

  1. Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /,money/waluty.php on line 5


Wie ktoś o co chodzi
PawelC
Wklej kawałek kodu włącznie z 5 linią
webmasts
  1. <?php
  2.  
  3. class WalutyNBP {
  4.  
  5. private $arrKursy = array();
  6. private $strData;
  7.  
  8. public function __construct($strEncoding='UTF-8',$strUrlXml='http://www.nbp.pl/Kursy/xml/'){
  9. $strUrlXml=$strUrlXml.$this->aktualny_xml().'.xml';
  10. $objXml = new XMLReader();
  11. if(function_exists('curl_init')){
  12. $objXml->XML($this->ccurl_fopen($strUrlXml));
  13. }
  14. else{
  15. ?>
PawelC
  1. <?php
  2.  
  3. class WalutyNBP {
  4.  
  5. private $arrKursy = array();
  6. private $strData;
  7.  
  8. public function __construct($strEncoding='UTF-8',$strUrlXml='http://www.nbp.pl/Kursy/xml/'){
  9. $strUrlXml=$strUrlXml.$this->aktualny_xml().'.xml';
  10. $objXml = new XMLReader();
  11. }
  12. if(function_exists('curl_init')){
  13. $objXml->XML($this->ccurl_fopen($strUrlXml));
  14.  
  15.  }
  16. else{
  17. ?>

Zobacz tak, parse error czyli gdzieś brakuje znaka albo jest wstawiony w złym miejscu.
webmasts
nadal to samo sadsmiley02.gif
ev45ive
zapewne masz php4 a ten kod pisany jest pod php5 winksmiley.jpg

usuń słowa "public" i "private" które są przed słowami "function", a wszystkie inne ( te po których niema "function") zamień na
"var"

*oczywiście bez cudzysłowiów "" winksmiley.jpg
mike
Cytat(ev45ive @ 9.01.2008, 21:31:46 ) *
usuń słowa "public" i "private" które są przed słowami "function", a wszystkie inne ( te po których niema "function") zamień na "var"
To nic nie da. Używany tam jest XMLReader, którego w PHP4 nie ma, więc zmiany te są bezcelowe.
~webmasts zainstaluj siobie PHP5 a nie wspierasz PHP4 - język już nierozwijany.
corradzisz
Hmm, od dwóch dni caly czas 0 mam na Euro. Coś się zmieniło? Ma ktoś jakieś rozwiązanie?
jarek_bolo
Witaj

Chyba czegoś nie rozumiem, albo masz błąd w kodzie.

Możesz wyjaśnić dlaczego w lini 100, w elseif`ie testujesz czy funkcja fsockopen nie istnieje (inne też tam testujesz), jeśli nie istnieje to wchodzimy do warunku i ... używamy fsockopen oraz reszty innych funkcji plikowych smile.gif

Kod
elseif(!function_exists('fsockopen') || !function_exists('fputs') || !function_exists('feof') || !function_exists('fgets'))


Nie powinno być raczej:
Kod
elseif(function_exists('fsockopen') && function_exists('fputs') && function_exists('feof') && function_exists('fgets'))

questionmark.gif

Bład wydaje się elementarny stąd aż wątpie, że możliwy i być może to ja czegoś nie rozumiem.

Pozdrawiam
Jarek Bolo
bim2
Ehm, znak ! to znak "przeciwiństwa". Jeśli dasz
if(!$true)
{

}
to ifka przejdzie jeśli $true = false; Tak samo w przypadku funkcji:
  1. <?php
  2. function test()
  3. {
  4. return false;
  5. }
  6.  
  7. if(!test())
  8. {
  9. echo 'to ci wyswietli';
  10. }
  11. ?>

Rozumiesz? smile.gif

EDIT: Ups, nie o to ci chodzi haha.gif Sorry, posta nie doczytałem. biggrin.gif
jarek_bolo
Mimo, że nie doczytałeś i błędną odpowiedź dałeś to i tak odpiszę dla wyklarowania o co mi chodzi.

Otóż Twoja funkcja test() zwraca false i jak w ifce sprawdzamy if (!test()) to ifka nas wpusci.
Teraz wracając do WalutyNBP.
function_exist() zwróci false jeśli funkcja nie istnieje, czyli przy takim zapisie if (!function_exist('fsockopen')) zostaniemy wpuszczeni do pętli jeśli fsockopen nie będzie dostępne, a tam w tej pętli używamy fsockopen(), stąd moje niezrozumienie smile.gif

Pozdrawiam
Jarek Bolo
bim2
Rozumiem smile.gif Jeszcze może wtrące, że można by sprawdzić czy allow_url_wrappers jest dozwolone smile.gif
parzol
Pozwolę zadać to pytanie tutaj aby nie otwierać nowego tematu.

Mianowicie chodzi mi o plik: http://www.nbp.pl//Kursy/xml/dir.txt

Ostatnie 6 cyfr to oczywiście data dodania. Analizując jednak plik na prędce widać że są dni w których nie ma aktualizacji.

Jakim cudem? blinksmiley.gif
bllitz
najprawdopodobniej są to weekendy i dni wolne
soldi
Mi klasa nie działała poprawnie, dopiero poprawienie funkcji aktualny_xml zmusiło klasę do poprawnej pracy.

Kod
     private function aktualny_xml($strTabela='a'){

         $fp = fsockopen("www.nbp.pl", 80, $errno, $errstr, 30);
         if (!$fp) {
             echo "$errstr ($errno) \n";
}         else {
             $out = "GET /Kursy/xml/dir.txt HTTP/1.1\r\n";
             $out .= "Host: www.nbp.pl\r\n";
             $out .= "Connection: Close\r\n\r\n";
             fwrite($fp, $out);
         while (!feof($fp)) {
             $arrPlikiXML[] = fgets($fp, 128);
             }
         fclose($fp);
}
         $arrPlikiXML = array_reverse ($arrPlikiXML);
         for($i=0; $i<=1; $i++){
             $strNazwa=trim($arrPlikiXML[$i]);
             if(substr($strNazwa,0,1)==$strTabela){
                 $strDzisiejszyXML=trim($arrPlikiXML[$i]);
             }
         }
         return $strDzisiejszyXML;
     }
dg2001
Witam, chciałem spróbować użyć powyższej klasy do pobierania walut z NBP z poprawkami wprowadzonymi przez SOLDI, jednak dostaję następujący komunikat błędu:

Warning: XMLReader::read() [xmlreader.read]: /home/jarkal/public_html/test/:11: parser error : Opening and ending tag mismatch: META line 0 and HEAD in public_html/test/conf/funkcje.php on line 87

Warning: XMLReader::read() [xmlreader.read]: </HEAD><BODY><TABLE width=500 border=0 cellspacing=10><TR><TD> in public_html/test/conf/funkcje.php on line 87

Warning: XMLReader::read() [xmlreader.read]: ^ in public_html/test/conf/funkcje.php on line 87

Warning: XMLReader::read() [xmlreader.read]: An Error Occured while reading in public_html/test/conf/funkcje.php on line 87

Poniżej skrypt od linijki 87 do 106.
Kod
while($objXml->read()){
               if($objXml->name === 'data_publikacji' && $objXml->nodeType==1){
                   $objXml->read();
                   $this->strData=$objXml->value;
               }
               if($objXml->depth==3){
                   if($j==4){
                       $j=0;
                       $this -> arrKursy[$arrWaluta[2]]=$arrWaluta;
                       $arrWaluta=array();
                   }
                   if($strEncoding!='ISO-8859-2'){
                       $arrWaluta[$j]=iconv('ISO-8859-2',$strEncoding,$objXml->value);
                   }
                   else{
                       $arrWaluta[$j]=$objXml->value;
                   }
                   $j++;
               }
           }


Zauważyłem jeszcze że czasem skrypt zadziała a czasem nie. Czy wina leży po stronie mojego serwera, czy coś z klasą czy NBP? Proszę o info.
okitoki
ja to tak rozwiązałem

Kod
<?php


class cWaluta
{
    public $dane = nill; // dane xmla
    public $numer = ""; // numer notowa..
    public $data  = ""; // data notowa..
    public $waluta = 'PLN';
    public $lista = array();
    private $znazwy = array('USD'=>'dolar ameryka..ski','HUF'=>'forint (W..gry)','DKK'=>'korona du..ska','EEK'=>'korona esto..ska',
                            'RON'=>'lej rumu..ski','BGN'=>'lew bu..garski','LVL'=>'..at ..otewski','PHP'=>'peso filipi..skie','XMN'=>'peso meksyka..skie',
                            'KRW'=>'won (Korea P..d.)');
    static $singlet = nill;
    
    static function nazwa_pliku($lokalizacja)
    {
        $nazwa = "";
        $d = dir($lokalizacja);
        while (false !== ($entry = $d->read()))
         if(eregi("([A-Za-z0-9]{1,})(.xml)",$entry))
               return $lokalizacja.$entry;
    }
    
    static function wwalucie($nazwa)
    {
        $tmp = cWaluta::$singlet;
        
        if(isset($tmp->lista[$nazwa]))
           $tmp->waluta = $nazwa;
        else  
           $tmp->waluta = 'PLN';
    }
    
    static function wWaluta($xmlfile)
    {
        if(cWaluta::$singlet == nill)
           cWaluta::$singlet = new cWaluta($xmlfile);
        
           return cWaluta::$singlet;
    }
    
    public function przewalutuj($kwota)
    {
        
        $waluta = $this->lista[$this->waluta];
        //print_r($waluta);
        $kw = $kwota / $waluta['kurs'];
        return sprintf("%01.2f {$waluta['kod']}",$kw * $waluta['licznik']);
    }
    
    private function zmien_nazwe($kod,$nazwa)
    {
        if(isset($this->znazwy[$kod]))
          return $this->znazwy[$kod];
        else
          return $nazwa;  
    }
    
    public function __construct($xmlfile)
    {
        
        $this->dane = new DOMDocument("1.0","utf-8");
        $this->dane->load($xmlfile);
        
        // pobranie mumeru kurs..w
        $doc = $this->dane->getElementsByTagName('numer_tabeli');
        $this->numer = $doc->item(0)->nodeValue;
        // pobranie daty kursu
        $doc = $this->dane->getElementsByTagName('data_publikacji');
        $this->data = $doc->item(0)->nodeValue;
        
        // tworzenie listy walut
        $doc = $this->dane;
        $wal = $doc->getElementsByTagName('pozycja');
        
        $this->lista['PLN']= array('nazwa'=>'Polski z..oty','licznik'=>'1','kurs'=>'1','kod'=>'PLN');
        
        foreach($wal as $item)
        {
         $kod = $item->getElementsByTagName('kod_waluty')->item(0)->nodeValue;    
         $nazwa = $this->zmien_nazwe($kod, $item->getElementsByTagName('nazwa_waluty')->item(0)->nodeValue);    
         $licznik = $item->getElementsByTagName('przelicznik')->item(0)->nodeValue;    
         $kurs = str_replace(',','.', $item->getElementsByTagName('kurs_sredni')->item(0)->nodeValue);
         $this->lista[$kod]= array('nazwa'=>$nazwa,'licznik'=>$licznik,'kurs'=>$kurs,'kod'=>$kod);    
        }
    }
    
}

?>


je to w singlecie
Kod
$plik = cWaluta::nazwa_pliku('/home/grobyopi/www.nbp.pl/Kursy/xml/'); // podajje lokalizacje gdzie jest zapisany xml
$waluty = cWaluta::wWaluta($plik);
cWaluta::wwalucie("USD"); // ustawiam walute
//w cenniku podaje
$waluty->przewalutuj(50); //to jest 50zł zwraca juz przeliczone


w cronie mam wpisane
Kod
codzienie o 12:59 "/bin/rm /home/grobyopi/www.nbp.pl/Kursy/xml/*"
codziennie o 13:00 "/usr/bin/wget -r  http://www.nbp.pl/Kursy/KursyA.html"


może ci się coś przyda smile.gif
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.