12

查看 URL 存在且响应不是 404 的最佳方法是什么?

4

5 回答 5

24

您可以使用get_headers($url)

手册中的示例 2

<?php
// By default get_headers uses a GET request to fetch the headers. If you
// want to send a HEAD request instead, you can do so using a stream context:
stream_context_set_default(
    array(
        'http' => array(
            'method' => 'HEAD'
        )
    )
);
print_r(get_headers('http://example.com'));

// gives
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
)

第一个数组元素将包含 HTTP 响应状态代码。你必须解析它。

请注意,get_headers示例中的函数将发出 HTTP HEAD 请求,这意味着它不会获取 URL 的正文。这比使用也会返回正文的 GET 请求更有效。

另请注意,通过设置默认上下文,任何使用 http 流上下文的后续调用现在都将发出 HEAD 请求。因此,请确保重置默认上下文以在完成后再次使用 GET。

PHP 还提供了变量 $http_response_header

$http_response_header数组与函数类似get_headers()。使用HTTP 包装器时,$http_response_header将填充 HTTP 响应标头。$http_response_header将在本地范围内创建。

如果你想下载远程资源的内容,你不想做两个请求(一个是查看资源是否存在,一个是获取它),而只是一个。在这种情况下,使用类似的东西file_get_contents来获取内容,然后从变量中检查标题。

于 2010-12-14T08:32:20.913 回答
0

@Gordon - 根据您的回答,这是一个更完整的库例程。它包括对 URL 有效性的一些初步检查、更多错误处理以及对返回的标头的解析。它还遵循任何重定向链进行合理数量的步骤。

class cLib {
    static $lasterror = 'No error set yet';
    /**
     * @brief See with a URL is valid - i.e. a page can be successfully retrieved from it without error
     * @param string $url The URL to be checked
     * @param int $nredirects The number of redirects check so far
     * @return boolean True if OK, false if the URL cannot be fetched
     */
    static function checkUrl($url, $nredirects = 0) {
        // First, see if the URL is sensible
        if (filter_var($url, FILTER_VALIDATE_URL) === false) {
            self::$lasterror = sprintf('URL "%s" did not validate', $url);
            return false;
        }
        // Now try to fetch it
        $headers = @get_headers($url);
        if ($headers == false) {
            $error = error_get_last();
            self::$lasterror = sprintf('URL "%s" could not be read: %s', $url, $error['message']);
            return false;
        }
        $status = $headers[0];
        $rbits = explode(' ', $status);
        if (count($rbits) < 2) {
            self::$lasterror = sprintf('Cannot parse status "%s" from URL "%s"', $status, $url);
            return false;
        }
        if (in_array($rbits[1], array(301, 302, 304, 307, 308))) {
            // This URL has been redirected. Follow the redirection chain
            foreach ($headers as $header) {
                if (cLib::startsWith($header, 'Location:')) {
                    if (++$nredirects > 10) {
                        self::$lasterror = sprintf('URL "%s" was redirected over 10 times: abandoned check', $url);
                        return false;
                    }
                    return self::checkUrl(trim(substr($header, strlen('Location:'))), $nredirects);
                }
            }
            self::$lasterror = sprintf('URL "%s" was redirected but location could not be identified', $url);
            return false;
        } 
        if ($rbits[1] != 200) {
            self::$lasterror = sprintf('URL "%s" returned status "%s"', $url, $status);
            return false;
        }
        return true;
    }
}

向@FranciscoLuz 道歉-如果您期望基于用户输入的错误,那么“@ and error_get_last”方法对我来说似乎非常明智-我认为使用 set_error_handler 没有什么更合适的。

顺便说一句,不确定我是否应该将其作为对@Gordon 答案的编辑,而不是作为单独的答案。有人可以建议吗?

于 2014-03-27T13:01:14.357 回答
0
public function isLink($url)
{
    $result = false;
    if (!filter_var($url, FILTER_VALIDATE_URL) === false) {
        $getHeaders = get_headers($url);
        $result = strpos($getHeaders[0], '200') !== false;
    }
    return $result;
}
于 2015-06-22T13:57:00.063 回答
0

我正在使用此函数,因为它还会验证并返回 URL 的协议(如果未找到)。

$theUrl = 'google.com';

function isValidURL($url) { 
    $urlRegex = '@(http(s)?)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
    if(preg_match($urlRegex, $url)){
        return preg_replace($urlRegex, "http$2://$4", $url);
    } else {
        return false;
    }
}

var_dump(isValidURL($theUrl));
于 2019-06-20T10:22:02.463 回答
0

我开发的一种识别 URL 是否确实存在的方法是以下 scrypt。可以通过更精细地分析错误返回来改进它。在那里,我通过估计只有“无法解析主机”的 URL 是错误的,执行了一个简单的错误返回。

function URL_EXIST($pUrl)
{
    $etat = true;
    $ch = curl_init($pUrl);
    curl_setopt($ch, CURLOPT_FAILONERROR, true);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    if (curl_exec($ch) === false)
    {
        $mes = strtolower(curl_error($ch));
        $cdt_wrong = preg_match('#could not resolve host#',$mes);
        $cdt_wrong |= preg_match('#404 not found#',$mes);
        if($cdt_wrong==true)
        {
            $etat = false;
        }
    }
    curl_close($ch);

    return $etat;
}

有一些例子,它工作得很好

于 2022-01-14T17:23:57.690 回答