Рабочее решение внизу описания!
Я запускаю PHP 5.4 и пытаюсь получить заголовки списка URL-адресов.
По большей части все работает нормально, но есть три URL-адреса, которые вызывают проблемы (и, вероятно, больше, при более широком тестировании).
'http://www.alealimay.com' 'http://www.thelovelist.net' 'http://www.bleedingcool.com'
Все три сайта отлично работают в браузере и производят следующие ответы заголовков:
(Из Сафари)
Обратите внимание, что все три ответа заголовка: Code = 200
Но получение заголовков через PHP, используя get_headers
…
stream_context_set_default(array('http' => array('method' => "HEAD"))); $headers = get_headers($url, 1); stream_context_set_default(array('http' => array('method' => "GET")));
… возвращает следующее:
url ...... "http://www.alealimay.com" headers | 0 ............................ "HTTP/1.0 400 Bad Request" | content-length ............... "378" | X-Synthetic .................. "true" | expires ...................... "Thu, 01 Jan 1970 00:00:00 UTC" | pragma ....................... "no-cache" | cache-control ................ "no-cache, must-revalidate" | content-type ................. "text/html; charset=UTF-8" | connection ................... "close" | date ......................... "Wed, 24 Aug 2016 01:26:21 UTC" | X-ContextId .................. "QIFB0I8V/xsTFMREg" | X-Via ........................ "1.0 echo109" url ...... "http://www.thelovelist.net" headers | 0 ............................ "HTTP/1.0 400 Bad Request" | content-length ............... "378" | X-Synthetic .................. "true" | expires ...................... "Thu, 01 Jan 1970 00:00:00 UTC" | pragma ....................... "no-cache" | cache-control ................ "no-cache, must-revalidate" | content-type ................. "text/html; charset=UTF-8" | connection ................... "close" | date ......................... "Wed, 24 Aug 2016 01:26:22 UTC" | X-ContextId .................. "aNKvf2RB/bIMjWyjW" | X-Via ........................ "1.0 echo103" url ...... "http://www.bleedingcool.com" headers | 0 ............................ "HTTP/1.1 403 Forbidden" | Server ....................... "Sucuri/Cloudproxy" | Date ......................... "Wed, 24 Aug 2016 01:26:22 GMT" | Content-Type ................. "text/html" | Content-Length ............... "5311" | Connection ................... "close" | Vary ......................... "Accept-Encoding" | ETag ......................... "\"57b7f28e-14bf\"" | X-XSS-Protection ............. "1; mode=block" | X-Frame-Options .............. "SAMEORIGIN" | X-Content-Type-Options ....... "nosniff" | X-Sucuri-ID .................. "11005"
Это происходит независимо от изменения stream_context
//stream_context_set_default(array('http' => array('method' => "HEAD"))); $headers = get_headers($url, 1); //stream_context_set_default(array('http' => array('method' => "GET")));
Производит тот же результат.
Никаких предупреждений или ошибок для любого из них (как правило, ошибки подавляются с помощью @get_headers
, но нет никакой разницы в любом случае).
Я проверил свой php.ini
и установил allow_url_fopen
в On
.
Я направляюсь к stream_get_meta_data
и не интересуюсь решениями CURL
. stream_get_meta_data
(и его сопровождающий fopen
) провалится в том же месте, что и get_headers
, поэтому исправление будет исправлено и в этом случае.
Обычно, если есть перенаправления, вывод выглядит следующим образом:
url ...... "http://www.startingURL.com/" headers | 0 ............................ "HTTP/1.1 301 Moved Permanently" | 1 ............................ "HTTP/1.1 200 OK" | Date | | "Wed, 24 Aug 2016 02:02:29 GMT" | | "Wed, 24 Aug 2016 02:02:32 GMT" | | Server | | "Apache" | | "Apache" | | Location ..................... "http://finishingURL.com/" | Connection | | "close" | | "close" | | Content-Type | | "text/html; charset=UTF-8" | | "text/html; charset=UTF-8" | | Link ......................... "; rel=\"https://api.w.org/\", ; rel=shortlink"
Почему сайты работают в браузерах, но сбой при использовании get_headers
?
Существуют разные сообщения SO, обсуждающие одно и то же, но решение для всех из них не относится к этому случаю:
POST
требует Content-Length
(я отправляю запрос HEAD
, содержимое не возвращается)
URL содержит данные UTF-8 (единственные символы в этих URL-адресах – от латинского алфавита)
Невозможно отправить URL-адрес с пробелами в нем (эти URL-адреса не содержат пробелов и очень обычны во всех отношениях)
(Спасибо Макс в ответах ниже, чтобы указать мне на правильный путь.)
Проблема заключается в том, что не существует заранее определенного user_agent
, без установки в php.ini
или объявления его в коде.
Итак, я меняю user_agent
чтобы имитировать браузер, сделать это, а затем вернуть его обратно к указанию значения (скорее всего, пустое).
$OriginalUserAgent = ini_get('user_agent'); ini_set('user_agent', 'Mozilla/5.0'); $headers = @get_headers($url, 1); ini_set('user_agent', $OriginalUserAgent);
Здесь найдено изменение агента пользователя.
Это происходит потому, что все три этих сайта проверяют заголовок UserAgent запроса и ответа с ошибкой в этом случае, если он не может быть сопоставлен. Функция get_headers
не отправляет этот заголовок. Вы можете попробовать cURL и этот фрагмент кода для получения содержимого сайтов:
$url = 'http://www.alealimay.com'; $c = curl_init($url); curl_setopt($c, CURLOPT_USERAGENT, 'curl/7.48.0'); curl_exec($c); var_dump(curl_getinfo($c));
UPD: Нет необходимости использовать cURL для настройки заголовка пользовательского агента. Это также можно сделать с помощью ini_set('user_agent', 'Mozilla/5.0');
а затем функция get_headers
будет использовать настроенное значение.