2012年11月16日金曜日

[PHP] PHPで特定のURLのHTTPステータスコードを取得する

リンク集のリンクが残念ながらサイト閉鎖や、URL変更などで404になることがある。
10個ぐらいなら手でチェックしてもいいが、100個、200個となるとさすがにうんざりする。
プログラムで調べるには、そのURLのHTTPステータスコードが404になるかどうか調べればよい。
なので、PHPでURLのHTTPステータスコードを返す関数をちょちょっと書いてみた。

//link・・・http://mio-koduki.blogspot.jp/2012/11/php-phpurlhttp.html
//第一引数・・・HTTPステータスコードを調べたいURL
//返り値・・・成功したらそのURLのHTTPステータスコード、失敗したらfalse
function get_http_status_code($url)
{
    if(($fp=fopen($url,'r',false,stream_context_create(array('http'=>array('ignore_errors'=>true)))))!==false)
    {
        fclose($fp);
        return preg_match('#^HTTP/\d\.\d (\d+) .+$#',$http_response_header[0],$matches)===1?(int)$matches[1]:false;
    }
    else
    {
        return false;
    }
}

とこんな感じになる。
file_get_contentsの代わりにfopenをつかってるのは、
file_get_contentsの場合はHTTPレスポンスボディを文字列に格納して返してくるので、
多少なりともメモリの消費が多くなるため、明示的に受け取る必要がないfopenを使ってる。
ただ、fopenでもfile_get_contentsでも、そのままだと401や404を返した際に返り値にfalseを返してくる。
それを防ぐために、fopenの第四引数にstream_context_createで作ったストリームコンテキストを渡してる。
この関数に連想配列で['http']['ignore_errors']にtrueを指定することによって
401や404の時にもきちんとファイルポインタリソースを返してくれるようにする。
また、突然初期化してない変数$http_response_headerを使ってるように見えるが、
じつはこれはPHPが自動的に代入してくれる変数で、
fopenなどの関数を使って通信が起こった際に(厳密にはHTTPラッパを使用する際に)、
HTTPレスポンスヘッダを配列で格納してくれる。
後は正規表現でHTTPレスポンスヘッダからHTTPステータスコードを取得して返しているだけである。

また、上と同じであるが、ちょっと見やすく整形したのがこっち。

//link・・・http://mio-koduki.blogspot.jp/2012/11/php-phpurlhttp.html
//第一引数・・・HTTPステータスコードを調べたいURL
//返り値・・・成功したらそのURLのHTTPステータスコード、失敗したらfalse
function get_http_status_code($url)
{
    $options=array
    (
        'http'=>array
        (
            'ignore_errors'=>true
        )
    );
    $fp=fopen($url,'r',false,stream_context_create($options));
    if($fp)
    {
        fclose($fp);
        $pattern='#^HTTP/\d\.\d (\d+) .+$#';
        if(preg_match($pattern,$http_response_header[0],$matches))
        {
            return (int)$matches[1];
        }
        else
        {
            false;
        }
    }
    else
    {
        return false;
    }
}

どちらがいいかはお好みで。

ポイントとなる変数・関数