@traestan
Web разработчик

Почему перестал работать код для получения котировок валют от цб рф, ссылаясь на «failed to open stream: Redirection limit reached, aborting»?

Доброго времени суток! У меня проблема, причем появилась только сегодня, код для получения котировок валют от цб рф перестал работать, ссылаясь на "failed to open stream: Redirection limit reached, aborting". Можете подсказать в чем проблема?

$url='http://www.cbr.ru/scripts/XML_daily.asp?date_req=01/01/2007&d=1' ;
        $context = array(
            'http'=>array('max_redirects' => 1)
        );
        $context = stream_context_create($context);  
         
    	if (!($fp = fopen($url,"r", false, $context))) {
		   die("could not open XML input");
		}
  • Вопрос задан
  • 12037 просмотров
Решения вопроса 1
function parseResponse( $response )
{
	$response_parts = explode( "\r\n\r\n", $response, 2 );
	$response = array();
	$cookie = array();
	
	$response['header'] = explode( "\r\n", $response_parts[0] );
	
	if ( preg_match_all( '/Set-Cookie: (.*?)=(.*?)(\n|;)/i', $response_parts[0], $matches ) ) {
		if ( !empty( $matches ) ) {
			foreach ( $matches[1] as $key => $value ) {
				$cookie[] = $value . '=' . $matches[2][$key] . ';';
			}
			$response['cookie'] = $cookie;
		}
	}
	$response['body'] = $response_parts[1];
	return $response;
}

$url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=10/12/2013';
$request = curl_init( $url );
$options = array(
	CURLOPT_HEADER => true,
    CURLOPT_NOBODY => false,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => false,
	CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0',
);
curl_setopt_array( $request, $options );
$result = curl_exec( $request );
if ( $result ) {
	$info = curl_getinfo( $request );
	$response = parseResponse( $result );
	$response['info'] = $info;
} else {
	$response = array(
		'number' => curl_errno( $request ),
		'error' => curl_error( $request ),
		'info' => curl_getinfo( $request )
	);
}
curl_close( $request );

print_r( $response );


вот такой код дает представление о происходящем.
после первой проверки меня видимо тоже забанили, но в браузере ссылка открывается. курл же отпинывается с 0 кодом. после добавления юзерагента стало редиректить на ту же страницу и так до бесконечности.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 10
alexkbs
@alexkbs
Не ЦБ единым... Есть прокси для получения курсов ЦБ РФ без лишних заморочек, во всевозможных форматах.
https://www.cbr-xml-daily.ru/
https://www.cbr-xml-daily.ru/daily.xml
https://www.cbr-xml-daily.ru/daily_utf8.xml
https://www.cbr-xml-daily.ru/daily_eng.xml
https://www.cbr-xml-daily.ru/daily_eng_utf8.xml
https://www.cbr-xml-daily.ru/daily_json.js
https://www.cbr-xml-daily.ru/daily_jsonp.js

Работает так: (пример с сайта)
<div id="USD">Доллар США $ — 00,0000 руб.</div>
<div id="EUR">Евро € — 00,0000 руб.</div>

<script>
function CBR_XML_Daily_Ru(rates) {
	var USDrate = rates.Valute.USD.Value.toFixed(4).replace('.', ',');
	var USD = document.getElementById('USD');
	USD.innerHTML = USD.innerHTML.replace('00,0000', USDrate);

	var EURrate = rates.Valute.EUR.Value.toFixed(4).replace('.', ',');
	var EUR = document.getElementById('EUR');
	EUR.innerHTML = EUR.innerHTML.replace('00,0000', EURrate);
}
</script>
<script src="https://www.cbr-xml-daily.ru/daily_jsonp.js"></script>

Огромное преимущество перед выкачкой курсов в XML в том что ничего не нужно качать и парсить на стороне сервера. Ничего такого, что в другом ответе, делать не нужно. Страницы открываются много шустрее.
Ответ написан
@sinelnikof
обновление
хмл формируется не сразу, а за какую то долю секунды если в этот момент приходит второй запрос то сервер считает это досом и рвет соединение, поэтому лучше написать метод который инициализирует запись в кеш нужных значений, перед тем как многократно к нему обратиться
Ответ написан
Комментировать
@VeMax
stream_context_create(array('http' => array('follow_location' => false)));
и посмотрите что вам вернется.
Ответ написан
@traestan Автор вопроса
Web разработчик
При curl var_dump() пустой
$URL = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=10/12/2013';
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_MAXREDIRS,1);
$sistem = curl_exec($ch);
var_dump($sistem);
curl_close($ch);
Ответ написан
Комментировать
@traestan Автор вопроса
Web разработчик
Пришла мысль что забанили ip или что то подобное так как открывается ссылка нормально. Поэтому видимо наша проблема((.
Ответ написан
Комментировать
видимо вам отдается 302 ошибка с редиректом куда-то, например на страницу с 403 ошибкой (забанили по ip?).
у меня ваш код работает и получает xml.
Ответ написан
@traestan Автор вопроса
Web разработчик
Видимо у них стоит проверка один раз можно только по api, или у них баг какой то.
Ответ написан
Комментировать
mongohtotech
@mongohtotech
У нас уже неделю подобные проблемы. То работает то нет. Здесь пишут была какая-то DDOS атака на них www.ec-rs.ru/index.php/news/industry-news/86-cb-ra...
Знает кто-нибудь аналогичный веб сервис для получения валютных котировок?
Ответ написан
@sinelnikof
у меня была похожая проблема советую обратить внимание каким образом у вас идет кеширование данных (у меня через apc cache) при частых запросах цб может откидывать по этому обязательно делаем кеш, и обновляем его каждые 2 -3 часа (я делал "сборщик мусора" по крону который такими делами занимался) чтоб проверить доступность сайта попробуйте его выкачать wget om но 70% это проблема в коде еще раз... правильно кешируйте и правильно обновляйте
Ответ написан
Комментировать
@sinelnikof
еще обновление в нем выкачиваем тупо к себе xml и потом ее разбираем затем все удаляем
$xml = new DOMDocument();
        $current = file_get_contents('http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y'));

        $file = __DIR__ . '-currensy.xml';
        file_put_contents($file, $current);

        if (@$xml->load($file)) {
            $this->list = array();

            $root = $xml->documentElement;
            $items = $root->getElementsByTagName('Valute');

            foreach ($items as $item) {
                $code = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
                $curs = $item->getElementsByTagName('Value')->item(0)->nodeValue;
                $this->list[$code] = floatval(str_replace(',', '.', $curs));
            }
            unlink($file);
            return true;
        }
        else
            unlink($file);
        return false;
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы