Парсер курса валют на PHP
Приветствую! После небольшого перерыва, продолжаю публиковать статьи для начинающих PHP программистов. На этот раз решил поделиться решением распространенной задачи — отображение текущего курса валют на сайте.
С начала, как обычно, постановка задачи:
Нам нужно отображать текущий курс доллара и евро относительно рубля, а также разницу между текущем курсом и вчерашним. Для простоты интеграции скрипта с различными сайтами, сделаем его без использования баз данных, курсы валют будут храниться в файле.
Реализация:
Получать текущий курс валюты будем с сайта ЦБРФ. Курс доступен в XML формате по адресу http://www.cbr.ru/scripts/XML_daily.asp. Для парсинга данных воспользуемся расширением PHP под названием SimpleXML (посмотрите phpinfo(), чтобы узнать установлено он или нет).
Стоит отметить, что XML на сайте центробанка обновляется раз в день, с понедельника по пятницу.
Алгоритм работы следующий: Читаем файл с данными. Если данные актуальны, то выводим информацию пользователю. В противном случае парсим XML с сайта ЦБРФ, сохраняем данные в файл и выводим пользователю. Данные в файле будем хранить в сериализованом виде, причем текущий курс и курс за прошедший день (для того чтобы показывать разницу).
Теперь можно написать сам класс для парсинга куса валют:
-
class curs
-
{
-
const REFRESH_INTERVAL=3600;
-
private $dataFile;
-
private $source = "http://www.cbr.ru/scripts/XML_daily.asp";
-
private $refreshTime;
-
public $cursNew;
-
public $cursOld;
-
-
private $error;
-
-
public function __construct($dataFile)
-
{
-
$this->dataFile=$dataFile;
-
-
if(!$f=fopen($this->dataFile, "r")) {
-
$this->refresh();
-
$this->error=true;
-
return false;
-
}
-
$data=fread($f, filesize($this->dataFile));
-
fclose($f);
-
$data=unserialize($data);
-
$this->refreshTime=$data['refresh_time'];
-
$this->cursNew=$data['curs']['new'];
-
$this->cursOld=$data['curs']['old'];
-
$this->refresh();
-
}
-
-
public function save()
-
{
-
$data=array(
-
"refresh_time"=>$this->refreshTime,
-
"curs" => array(
-
"new"=>$this->cursNew,
-
"old"=>$this->cursOld
-
)
-
);
-
-
-
if(!$f=fopen($this->dataFile, "w+")) return false;
-
fwrite($f, serialize($data));
-
fclose($f);
-
}
-
-
public function refresh()
-
{
-
if((time()-self::REFRESH_INTERVAL)$this->refreshTime) return true;
-
-
if(isset($this->cursNew['date']) && $this->cursNew['date']>=$this->get_timestamp(date("d.m.y"))) return true;
-
-
$new_data=$this->readFromCbr();
-
$this->refreshTime=time();
-
if(is_array($new_data)){
-
if($new_data['date']>$this->cursNew['date']){
-
$this->cursOld=$this->cursNew;
-
$this->cursNew=$new_data;
-
$this->save();
-
} else {
-
return true;
-
}
-
} else {
-
return false;
-
}
-
}
-
-
private function readFromCbr()
-
{
-
if(!$xml=simplexml_load_file($this->source)) return false;
-
$curs['date']=self::get_timestamp($xml->attributes()->Date);
-
foreach($xml->Valute as $m){
-
if($m->CharCode=="USD" || $m->CharCode=="EUR"){
-
$curs[(string)$m->CharCode]=(float)str_replace(",", ".", (string)$m->Value);
-
}
-
}
-
return $curs;
-
}
-
-
public static function get_timestamp($date)
-
{
-
list($d, $m, $y) = explode('.', $date);
-
return mktime(0, 0, 0, $m, $d, $y);
-
}
-
}
Немного о том как пользоваться классом. Конструктор принимает один параметр — путь к файлу, в котором будут хранится данные парсинга валют (файл должен быть доступен для записи).
-
$curs=new curs('./cursData.txt'); //Задаем файл для хранения данных
-
$curs->cursNew["date"]; //Актуальая дата курса
-
$curs->cursNew["USD"]; //Курс евро текущий
-
$curs->cursNew["EUR"]; //Курс доллара текущий
-
$curs->cursOld["USD"]; //Курс евро вчерашний
-
$curs->cursOld["EUR"]; //Курс доллара вчерашний
Скачать пример можно здесь
А у меня почему-то вот что получилось.
Parse error: syntax error, unexpected ‘&’ in … on line 16.
$this->dataFile=$dataFile;
С чем связано возникновение ошибки?
Подскажите пожалуйста.
Скачайте код примера здесь. При копировании кода со страницы, он может не работать из-за HTML тегов.
Теперь вот что говорит
Warning: fread() []: Length parameter must be greater than 0 in ….\curs.php on line 29
$data=fread($f, filesize($this->dataFile));
Может быть это связано с версиями программ которыми я пользуюсь? У вас ведь все работает…
Закачала на сервер три файла (curs.php, curs.dat, curs.dat) в одну директорию выдает:
Parse error: syntax error, unexpected T_CONST, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or ‘}’ in /home/vipcentr/i/p/k/ipkapitonov/public_html/curs.php on line 11
const REFRESH_INTERVAL=3600;
Что же я не так делаю?
Извиняюсь третий файл не правильно указала, cursData.txt
@Эльвира
Это нормально, при первом запуске скрипта. Он предупреждает, что файл с данными пустой. Запустите скрипт еще раз и ошибка исчезнет.
P.S. Файл с данными должен быть доступен для записи
@Эльвира
Parse error: syntax error, unexpected T_CONST, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR Это, вероятно, из-за того что пропустили скобку, ‘;’ или что-то в этом духе.
Верно всё исчезло, на локальном сервере пустая страница отбражается, а на удаленном все та же ошибка со скобками, подсветкой проверила как бы все на месте, а потом я ничего не меняла внутри скрипта, только вот теперь чмод добавила 777, в трех файлах, правильно? а все равно почему-то не работает?
@Эльвира
Возможно на сервере версия PHP ниже 5.2
@Эльвира
То что отображается пустая страница, это правильно. Для вывода информации нужно прописать:
echo $curs->cursNew["USD"]; //Выведет курс евро
echo $curs->cursNew["EUR"]; //Выведет курс доллара
и т. д.
Получилось, здорово, php это просто чудо какое-то. Спасибо большое, Вам Роман.
Спасибо большое, я давно искал ссылочку на xml курса валют!
Парсер напишу сам! И еще: подскажите где хороший xml c погодой, а то на gismeteo платный стал! =(
Нет ничего проще .
Постоянно пишет-
Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение
Может сталкивались с этим?
@Евгений
Возможно, виноват файрвол.
Огромнейшее спасибо Roman, так заработался, что о файрволе и не подумал.
Все отлично работает!
Уважаемый Роман!
Очень понравился парср, но вот что-то непонятка нарисовалась:
include «curs.php»;
$curs=new curs(‘./cursData.txt’);
$curs->cursNew["date"];
$curs->cursNew["USD"];
$curs->cursNew["EUR"];
$curs->cursOld["USD"];
$curs->cursOld["EUR"];
echo $curs->cursOld["USD"];
echo $curs->cursNew["USD"];
ужас в том, что файл cursData.txt не изменился и, соответственно, cursOld не выводится. Но если удалить текстовый файл и запустить скрипт — он появляеся уже обновленный, с новыми данными… Что не так?
прикольно будем пользоваться…..