Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Довольно часто владельцы сайтов просят поставить на свои проекты индикаторы курсов валют и их динамику. Можно воспользоваться готовыми информерами, но они не всегда позволяют должным образом настроить внешний вид.
Поэтому сейчас мы сделаем парсер курса валют на php с сайта cbr.ru, отобразим динамику изменения курса и в конце закешируем полученные данные для эффективного использования в 1с-Битрикс.
Получаем и обрабатываем данные
Самые свежие данные мы будем получать из xml-файла, который совершенно бесплатно предоставляет нам сайт cbr.ru. Адрес файла имеет вид — http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1=10/02/2011&date_req2=26/02/2011&VAL_NM_RQ=R01235
Здесь date_req1 — дата начала периода; date_req2 — дата конца периода, за который нужна динамика; VAL_NM_RQ — идентификатор валюты (R01235 для USD, R01239 для EUR)
Структура полученного xml-файла такова:
<ValCurs ID=
"R01239"
DateRange1=
"18/02/2011"
DateRange2=
"19/02/2011"
name=
"Foreign Currency Market Dynamic"
>
<Record
Date
=
"18.02.2011"
Id=
"R01239"
>
<Nominal>
1
</Nominal>
<Value>
39,6821
</Value>
</Record>
<Record
Date
=
"19.02.2011"
Id=
"R01239"
>
<Nominal>
1
</Nominal>
<Value>
39,7682
</Value>
</Record>
</ValCurs>
Как мы видим, записи идут в порядке возрастания даты и нужное значение хранится в теге и его легко получить регулярным выражением.
// формируем 2 даты - "завтра" и несколько дней назад
$curDate
=
date
(
'd/m/Y'
,
mktime
(0,0,0,
date
(
"n"
),
date
(
"j"
)+1,
date
(
"Y"
)));
$curDate2
=
date
(
'd/m/Y'
,
mktime
(0,0,0,
date
(
"n"
),
date
(
"j"
)-10,
date
(
"Y"
)));
// xml с сайта ЦБ РФ
$currencyXML
=
file_get_contents
(
'http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='
.
$curDate2
.
'&date_req2='
.
$curDate
.
'&VAL_NM_RQ=R01235'
);
// убираем переносы строк
$currencyXML
=
str_replace
(Array(
"\r\n"
,
"\n"
,
"\r"
),
''
,
$currencyXML
);
// регулярное выражение получает все значения тегов <Value> в массив $arValues
preg_match_all(
'#<Value>(.*?)</Value>#'
,
$currencyXML
,
$arValues
, PREG_PATTERN_ORDER);
// если совпадений больше одного, т.е. в xml были данные как минимум за 2 дня и можно отследить динамику
if
(
count
(
$arValues
[1])>=2) {
// развернем массив, чтобы первыми шли свежие данные
$arValues
[1] =
array_reverse
(
$arValues
[1]);
// сделаем резделителем целой и дробной части точку
$kurs
=
str_replace
(
","
,
"."
,
$arValues
[1][0]);
// разница курсов, округленная до 4х знаков после запятой
$diff
=
round
(
floatval
(
str_replace
(
","
,
"."
,
$arValues
[1][0])) -
floatval
(
str_replace
(
","
,
"."
,
$arValues
[1][1])), 4);
}
«Завтра» и «несколько дней назад» выбраны не просто так — курс валюты иногда появляется заранее, а иногда не появляется вообще, например по воскресеньям или праздникам.
Теперь можно вывести в нужном месте значения переменных $kurs и $diff и радоваться полученному результату:)
Но дергать xml на каждом хите пользователя нехорошо, поэтому все это дело нужно закешировать
Кешируем результат в 1с-Битрикс
Кешировать будем результирующий html-код, для этого используем класс CPageCache.
<?
if
(!defined(
"B_PROLOG_INCLUDED"
) || B_PROLOG_INCLUDED!==true)
die
();
// создаем объект
$obCache
=
new
CPageCache;
// время кеширования - 6 часов
$life_time
= 60*60*6;
// формируем идентификатор кеша в зависимости от всех параметров
// которые могут повлиять на результирующий HTML
$cache_id
=
"iammegacachhhhhhhhhhhe"
;
// инициализируем буферизирование вывода
if
(
$obCache
->StartDataCache(
$life_time
,
$cache_id
,
"/"
)):
// формируем 2 даты - "завтра" и несколько дней назад
$curDate
=
date
(
'd/m/Y'
,
mktime
(0,0,0,
date
(
"n"
),
date
(
"j"
)+1,
date
(
"Y"
)));
$curDate2
=
date
(
'd/m/Y'
,
mktime
(0,0,0,
date
(
"n"
),
date
(
"j"
)-10,
date
(
"Y"
)));
// xml с сайта ЦБ РФ
$currencyXML
=
file_get_contents
(
'http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1='
.
$curDate2
.
'&date_req2='
.
$curDate
.
'&VAL_NM_RQ=R01235'
);
// убираем переносы строк
$currencyXML
=
str_replace
(Array(
"\r\n"
,
"\n"
,
"\r"
),
''
,
$currencyXML
);
// регулярное выражение получает все значения тегов <Value> в массив $arValues
preg_match_all(
'#<Value>(.*?)</Value>#'
,
$currencyXML
,
$arValues
, PREG_PATTERN_ORDER);
// если совпадений больше одного, т.е. в xml были данные как минимум за 2 дня и можно отследить динамику
if
(
count
(
$arValues
[1])>=2) {
// развернем массив, чтобы первыми шли свежие данные
$arValues
[1] =
array_reverse
(
$arValues
[1]);
// сделаем резделителем целой и дробной части точку
$kurs
=
str_replace
(
","
,
"."
,
$arValues
[1][0]);
// разница курсов, округленная до 4х знаков после запятой
$diff
=
round
(
floatval
(
str_replace
(
","
,
"."
,
$arValues
[1][0])) -
floatval
(
str_replace
(
","
,
"."
,
$arValues
[1][1])), 4);
}
else
{
$kurs
=
""
;
$diff
=
""
;
}?>
USD: <?=
$kurs
?><br />
Изменение: <?=
$diff
?>
<?
// записываем предварительно буферизированный вывод в файл кеша
$obCache
->EndDataCache();
endif
;
?>
Пара слов о выборе времени кеширования и идентификатора кеша. Так как на всех страницах сайта результат работы скрипта одинаковый, то есть смысл оставить идентификатором константу, тогда будет один периодически обновляемый (6 часов в примере) файл кеша. Также можно привязать идентификатор к дате и увеличить время жизни кеша, тогда новые данные будут тянуться ровно 1 раз в сутки, но на каждый день появится отдельный файл.
Это не единственный способ получить данные о курсах валют и направлен, в первую очередь, на определение динамики их изменения. Если нужны только текущие значения, то логичнее его парсить из xml-файла http://www.cbr.ru/scripts/XML_daily.asp, который содержит сразу все валюты.