我如何检查一个URL是否存在(不是404)在PHP?


当前回答

检查url是在线还是离线——

function get_http_response_code($theURL) {
    $headers = @get_headers($theURL);
    return substr($headers[0], 9, 3);
}

其他回答

cURL可以返回HTTP代码,我不认为所有额外的代码是必要的?

function urlExists($url=NULL)
    {
        if($url == NULL) return false;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $data = curl_exec($ch);
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch); 
        if($httpcode>=200 && $httpcode<300){
            return true;
        } else {
            return false;
        }
    }

在检查报头是否有404错误时,需要考虑的一件事是站点不会立即生成404错误。

很多网站会检查PHP/ASP(等等)源代码中是否存在某个页面,然后将您转到404页面。在这些情况下,头基本上是由生成的404头扩展的。在这种情况下,404错误不会出现在头文件的第一行,而是第10行。

$array = get_headers($url);
$string = $array[0];
print_r($string) // would generate:

Array ( 
[0] => HTTP/1.0 301 Moved Permanently 
[1] => Date: Fri, 09 Nov 2018 16:12:29 GMT 
[2] => Server: Apache/2.4.34 (FreeBSD) LibreSSL/2.7.4 PHP/7.0.31 
[3] => X-Powered-By: PHP/7.0.31 
[4] => Set-Cookie: landing=%2Freed-diffuser-fig-pudding-50; path=/; HttpOnly 
[5] => Location: /reed-diffuser-fig-pudding-50/ 
[6] => Content-Length: 0 
[7] => Connection: close 
[8] => Content-Type: text/html; charset=utf-8 
[9] => HTTP/1.0 404 Not Found 
[10] => Date: Fri, 09 Nov 2018 16:12:29 GMT 
[11] => Server: Apache/2.4.34 (FreeBSD) LibreSSL/2.7.4 PHP/7.0.31 
[12] => X-Powered-By: PHP/7.0.31 
[13] => Set-Cookie: landing=%2Freed-diffuser-fig-pudding-50%2F; path=/; HttpOnly 
[14] => Connection: close 
[15] => Content-Type: text/html; charset=utf-8 
) 

我运行一些测试,看看我的网站上的链接是否有效-提醒我当第三方改变他们的链接。我有一个网站的问题,有一个配置不良的证书,这意味着php的get_headers不能工作。

所以,我读到卷曲更快,并决定给一个尝试。然后我在领英上遇到了一个问题,给了我一个999错误,后来证明是用户代理的问题。

我不关心证书是否对该测试无效,也不关心响应是否为重定向。

然后我认为使用get_headers无论如何,如果卷曲失败....

试试看....

/**
 * returns true/false if the $url is valid.
 *
 * @param string $url assumes this is a valid url.
 *
 * @return bool
 */
private function urlExists(string $url): bool
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);     // do not output response in stdout
    curl_setopt($ch, CURLOPT_NOBODY, true);             // this does a head request to make it faster.
    curl_setopt($ch, CURLOPT_HEADER, true);             // just the headers
    curl_setopt($ch, CURLOPT_SSL_VERIFYSTATUS, false);  // turn off that pesky ssl stuff - some sys admins can't get it right.
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    // set a real user agent to stop linkedin getting upset.
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36');
    curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if (($http_code >= 200 && $http_code < 400) || $http_code === 999) {
        curl_close($ch);
        return true;
    }
    //$error = curl_error($ch); // used for debugging.
    curl_close($ch);

    // just try the get_headers - it might work!
    stream_context_set_default(
        ['http' => ['method' => 'HEAD']]
    );
    $file_headers = @get_headers($url);

    if ($file_headers !== false) {
        $response_code = substr($file_headers[0], 9, 3);
        return $response_code >= 200 && $response_code < 400;
    }

    return false;
}

这是一个解决方案,只读取源代码的第一个字节…如果file_get_contents失败,返回false…这也适用于远程文件,如图像。

 function urlExists($url)
{
    if (@file_get_contents($url,false,NULL,0,1))
    {
        return true;
    }
    return false;
}
function url_exists($url) {
    $headers = @get_headers($url);
    return (strpos($headers[0],'200')===false)? false:true;
}