Я обучаю себя основам парсинга и обнаружил, что иногда URL-адреса, которые я вводю в свой код, возвращают 404, что склеивает весь остальной мой код.
Поэтому мне нужен тест в верхней части кода, чтобы проверить, возвращает ли URL-адрес 404 или нет.
Это может показаться довольно простой задачей, но Google не дает мне никаких ответов. Боюсь, я ищу не то.
Один блог рекомендовал мне использовать это:
$valid = @fsockopen($url, 80, $errno, $errstr, 30);
а затем проверьте, действительно ли $ действителен, если он пуст или нет.
Но я думаю, что URL-адрес, который вызывает у меня проблемы, имеет перенаправление, поэтому $ valid оказывается пустым для всех значений. Или, может быть, я еще что-то делаю не так.
Я также изучил «запрос головы», но мне еще не удалось найти никаких реальных примеров кода, с которыми я мог бы поиграть или попробовать.
Предложения? А что насчет завитка?






Нашел такой ответ здесь:
if (($twitter_XML_raw=file_get_contents($timeline))==false){
// Retrieve HTTP status code
list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);
// Check the HTTP Status code
switch($status_code) {
case 200:
$error_status = "200: Success";
break;
case 401:
$error_status = "401: Login failure. Try logging out and back in. Password are ONLY used when posting.";
break;
case 400:
$error_status = "400: Invalid request. You may have exceeded your rate limit.";
break;
case 404:
$error_status = "404: Not found. This shouldn't happen. Please let me know what happened using the feedback link above.";
break;
case 500:
$error_status = "500: Twitter servers replied with an error. Hopefully they'll be OK soon!";
break;
case 502:
$error_status = "502: Twitter servers may be down or being upgraded. Hopefully they'll be OK soon!";
break;
case 503:
$error_status = "503: Twitter service unavailable. Hopefully they'll be OK soon!";
break;
default:
$error_status = "Undocumented error: " . $status_code;
break;
}
По сути, вы используете метод «file get contents» для получения URL-адреса, который автоматически заполняет переменную заголовка HTTP-ответа кодом состояния.
ирония - ссылка 404
Если вы используете PHP curl привязки, вы можете проверить код ошибки, используя curl_getinfo как таковой:
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if ($httpCode == 404) {
/* Handle 404 here. */
}
curl_close($handle);
/* Handle $response here. */
Я еще не знаком с cURL, поэтому мне не хватает нескольких концепций. Что мне делать с переменной $ response внизу? Что в нем содержится?
@bflora, я ошибся в коде. (Исправлю через секунду.) Вы можете увидеть документацию для curl_exec на сайте PHP.
@bflora $ response будет содержать содержимое $ url, чтобы вы могли делать дополнительные вещи, например проверять содержимое на наличие определенных строк или что-то еще. В вашем случае вы просто заботитесь о состоянии 404, поэтому вам, вероятно, не нужно беспокоиться о $ response.
Интересно. Сейчас я использую $ html = new DOMDocument (); @ $ html-> loadHTMLFile ($ url); $ xml = simplexml_import_dom ($ html); Чтобы получить содержимое URL-адресов и пройти по ним, чтобы получить элементы, которые мне нужно вставить. Было бы лучше curl?
@bflora, Если вы отправите запрос на сервер, он обработает ваш запрос и вернет HTTP-код вместе с данными. Если вы запросите дважды, ваш скрипт будет примерно в два раза медленнее (обычно ввод-вывод - самая медленная часть). Если вы воспользуетесь данными, полученными при первом запросе, это будет быстрее.
@bflora, Кроме того, в PHP есть опция, которая запрещает использовать fopen () URL (и DOMDocument, вероятно, использует fopen () в loadHTMLFile ()). curl лучше, и он обеспечивает гораздо больше возможностей настройки (например, вы можете запросить сжатие ответа или на другом языке).
Что делать, если вы хотите загружать только заголовки, а не загружать файл целиком?
@patrick, тогда вам нужно указать curl_setopt($handle, CURLOPT_NOBODY, true); перед запуском curl_exec
могу я получить пример в реальном времени?
А как насчет перенаправления, кода 302, на 404? Где CURLOPT_FOLLOWLOCATION?
Как предлагает Strager, изучите использование cURL. Вам также может быть интересно установить CURLOPT_NOBODY с curl_setopt, чтобы пропустить загрузку всей страницы (вам нужны только заголовки).
+1 за упоминание меня ^ W ^ Wпредоставление более эффективной альтернативы в случае, когда нужно проверять только заголовок. знак равно
это всего лишь кусок кода, надежда работает на тебя
$ch = @curl_init();
@curl_setopt($ch, CURLOPT_URL, 'http://example.com');
@curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
@curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = @curl_exec($ch);
$errno = @curl_errno($ch);
$error = @curl_error($ch);
$response = $response;
$info = @curl_getinfo($ch);
return $info['http_code'];
Если у вас запущен php5, вы можете использовать:
$url = 'http://www.example.com';
print_r(get_headers($url, 1));
В качестве альтернативы с php4 пользователь добавил следующее:
/**
This is a modified version of code from "stuart at sixletterwords dot com", at 14-Sep-2005 04:52. This version tries to emulate get_headers() function at PHP4. I think it works fairly well, and is simple. It is not the best emulation available, but it works.
Features:
- supports (and requires) full URLs.
- supports changing of default port in URL.
- stops downloading from socket as soon as end-of-headers is detected.
Limitations:
- only gets the root URL (see line with "GET / HTTP/1.1").
- don't support HTTPS (nor the default HTTPS port).
*/
if (!function_exists('get_headers'))
{
function get_headers($url,$format=0)
{
$url=parse_url($url);
$end = "\r\n\r\n";
$fp = fsockopen($url['host'], (empty($url['port'])?80:$url['port']), $errno, $errstr, 30);
if ($fp)
{
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: ".$url['host']."\r\n";
$out .= "Connection: Close\r\n\r\n";
$var = '';
fwrite($fp, $out);
while (!feof($fp))
{
$var.=fgets($fp, 1280);
if (strpos($var,$end))
break;
}
fclose($fp);
$var=preg_replace("/\r\n\r\n.*\$/",'',$var);
$var=explode("\r\n",$var);
if ($format)
{
foreach($var as $i)
{
if (preg_match('/^([a-zA-Z -]+): +(.*)$/',$i,$parts))
$v[$parts[1]]=$parts[2];
}
return $v;
}
else
return $var;
}
}
}
Оба будут иметь результат, подобный:
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Sat, 29 May 2004 12:28:14 GMT
[Server] => Apache/1.3.27 (Unix) (Red-Hat/Linux)
[Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
[ETag] => "3f80f-1b6-3e1cb03b"
[Accept-Ranges] => bytes
[Content-Length] => 438
[Connection] => close
[Content-Type] => text/html
)
Поэтому вы можете просто проверить, что ответ заголовка в порядке, например:
$headers = get_headers($url, 1);
if ($headers[0] == 'HTTP/1.1 200 OK') {
//valid
}
if ($headers[0] == 'HTTP/1.1 301 Moved Permanently') {
//moved or redirect page
}
Я сделал несколько улучшений форматирования вашего ответа, я также добавил возможность для https: get_headers($https_url,1,443);. Я уверен, что он будет работать, хотя его нет в стандартной функции get_headers() .. Не стесняйтесь протестировать его и сообщить статус для него.
хороший обходной путь для php4, но для таких случаев у нас есть HTTP-метод HEAD.
Значит, это будет быстрее, чем метод curl?
Это решение недействительно, если целевой URL-адрес перенаправляет на 404. В этом случае $ headers [0] будет кодом перенаправления, а окончательный код 404 будет добавлен где-то позже в возвращаемом массиве.
В конечном итоге это создает больше проблем, чем это того стоит в php, чтобы отфильтровать фактический код из результирующей строки при попытке просто обработать код состояния в сценарии, в отличие от вывода результата для чтения.
Kzqai, в этом нет никаких проблем, вызывать целое приложение для выполнения этой работы просто глупо, если у вас нет других применений для curl.
get_headers($url, 1)[0] === "HTTP/1.1 200 OK" был именно тем, что я хотел! Большое спасибо!
С помощью кода незнакомца вы также можете проверить CURLINFO_HTTP_CODE на наличие других кодов. Некоторые веб-сайты не сообщают об ошибке 404, а просто перенаправляют на пользовательскую страницу 404 и возвращают 302 (перенаправление) или что-то подобное. Я использовал это, чтобы проверить, существует ли на сервере настоящий файл (например, robots.txt) или нет. Очевидно, что этот тип файла не вызвал бы перенаправления, если бы он существовал, но если бы он не был перенаправлен на страницу 404, которая, как я сказал ранее, может не иметь кода 404.
function is_404($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
/* If the document has loaded successfully without any redirection or error */
if ($httpCode >= 200 && $httpCode < 300) {
return false;
} else {
return true;
}
}
+1 за использование "успешных" HTTP-кодов вместо 404 ... Пользователь может получить 408 Request Timeout, а не 404
Работал как шарм. Я использую это, чтобы проверить, есть ли еще статья на ebay.
Для тех, кто ожидает, что приведенный выше код будет работать с https, попробуйте добавить следующее: curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, FALSE);
но это также вернет 404 = true, если есть законное перенаправление 302?
Если вы ищете самое простое решение и то, которое вы можете попробовать за один раз, на php5 сделайте
file_get_contents('www.yoursite.com');
//and check by echoing
echo $http_response_header[0];
кстати, если это сделать и URL-адрес 404, возникает предупреждение, вызывающее вывод.
проще сделать $ isExists = @file_get_contents ('www.yoursite.com'); if ($ isExists! == true) {echo "возвращает 404"}
поставить пробный улов, затем обработать 404 с уловом
В качестве дополнительной подсказки к хорошо принятому ответу:
При использовании варианта предлагаемого решения возникли ошибки из-за настройки php max_execution_time. Итак, я сделал следующее:
set_time_limit(120);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_NOBODY, true);
$result = curl_exec($curl);
set_time_limit(ini_get('max_execution_time'));
curl_close($curl);
Сначала я установил ограничение по времени на большее количество секунд, в конце я вернул его к значению, определенному в настройках php.
хххмммм ... кроме того ... ваш код потребляет меньше ресурсов, потому что вы не возвращаете контент ... тем не менее, если вы можете добавить обратную передачу в false, тогда вы можете сэкономить много ресурсов, когда люди используют несколько вызовов ... новички не думают много и поэтому это причина для 40 голосов за ... это нормально ...
Вы также можете использовать этот код, чтобы увидеть статус любой ссылки:
<?php
function get_url_status($url, $timeout = 10)
{
$ch = curl_init();
// set cURL options
$opts = array(CURLOPT_RETURNTRANSFER => true, // do not output to browser
CURLOPT_URL => $url, // set URL
CURLOPT_NOBODY => true, // do a HEAD request only
CURLOPT_TIMEOUT => $timeout); // set timeout
curl_setopt_array($ch, $opts);
curl_exec($ch); // do it!
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE); // find HTTP status
curl_close($ch); // close handle
echo $status; //or return $status;
//example checking
if ($status == '302') { echo 'HEY, redirection';}
}
get_url_status('http://yourpage.comm');
?>
Вот краткое решение.
$handle = curl_init($uri);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle,CURLOPT_HTTPHEADER,array ("Accept: application/rdf+xml"));
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if ($httpCode == 200||$httpCode == 303)
{
echo "you might get a reply";
}
curl_close($handle);
В вашем случае вы можете заменить application/rdf+xml на все, что используете.
приложение; протестировал эти 3 метода с учетом производительности.
Результат, по крайней мере, в моей тестовой среде:
Curl побеждает
Этот тест проводится с учетом того, что нужны только заголовки (noBody). Попробуй себя:
$url = "http://de.wikipedia.org/wiki/Pinocchio";
$start_time = microtime(TRUE);
$headers = get_headers($url);
echo $headers[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
$start_time = microtime(TRUE);
$response = file_get_contents($url);
echo $http_response_header[0]."<br>";
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
$start_time = microtime(TRUE);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_NOBODY, 1); // and *only* get the header
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
// if ($httpCode == 404) {
// /* Handle 404 here. */
// }
echo $httpCode."<br>";
curl_close($handle);
$end_time = microtime(TRUE);
echo $end_time - $start_time."<br>";
<?php
$url= 'www.something.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.4");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT,10);
curl_setopt($ch, CURLOPT_ENCODING, "gzip");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$output = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $httpcode;
?>
Это даст вам истину, если url не вернет 200 OK
function check_404($url) {
$headers=get_headers($url, 1);
if ($headers[0]!='HTTP/1.1 200 OK') return true; else return false;
}
Это намного быстрее, чем использование cURL, если вы хотите выполнить простую проверку bool для URL-адреса. Спасибо.
Вот способ!
<?php
$url = "http://www.google.com";
if (@file_get_contents($url)){
echo "Url Exists!";
} else {
echo "Url Doesn't Exist!";
}
?>
Этот простой скрипт просто запрашивает URL-адрес своего исходного кода. Если запрос выполнен успешно, будет выведено «URL существует!». В противном случае будет выведено «URL не существует!».
Эта функция возвращает код состояния URL-адреса в PHP 7:
/**
* @param string $url
* @return int
*/
function getHttpResponseCode(string $url): int
{
$headers = get_headers($url);
return substr($headers[0], 9, 3);
}
Пример:
echo getHttpResponseCode('https://www.google.com');
//displays: 200
Интересно - я никогда раньше не слышал об этом волшебном глобале. php.net/manual/en/reserved.variables.httpresponseheader.php