curlでサイトにアクセスできない時の対処法(php)


はじめに

php 7.3
スクレイピングでアクセスできなくてかなり悩んだのでまとめてみました。

リダイレクトされる

ページURLが変更されてリダイレクトされている場合です。
この場合は、オプションでリダイレクト先へ飛ぶようにします

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_FOLLOWLOCATION => true, //リダイレクトを辿る
        CURLOPT_MAXREDIRS => 10,  //リダイレクト数
        CURLOPT_AUTOREFERER => true,  //リダイレクトした際のRefererのURLを自動セット
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

HTTPSにアクセスしてエラー

サーバー証明書の検証でエラーが起きた場合です。
この場合は、オプションで証明書の検証をしないように設定して回避します

test.php
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_SSL_VERIFYPEER => false, //証明書の検証を行わないよう設定
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

ブラウザで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
どのブラウザからのアクセスかをサーバ側で判定してエラーページに遷移させたりします。
この場合は、ヘッダーのユーザーエージェントを偽装してアクセスします。
ユーザーエージェントの中身は変更していただいても構いません。

test.php
    $headers = array(
        "HTTP/1.0",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  //ヘッダーのUser-Agentに通常のPCからのアクセスのように見せかけます
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

Cookieで除外される

ブラウザからは見えるのに、プログラムではアクセスできない場合です。
Cookieの中身を判定して、エラーページに遷移させたりします。
curlではCookieを明示的に付与しなければ空でアクセスされるため、そういったプログラムでのアクセスを回避するために設定されている場合があります。
この場合は、サーバからCookieを受け取り、そのCookieを使用してアクセスするようにします。

test.php
    $headers = array(
        "HTTP/1.0",
        "Connection:keep-alive",
        "User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_COOKIEJAR => "test.cookie", //Cookieを取得してカレントディレクトリにtest.cookieファイルとして保存
        CURLOPT_COOKIEFILE => "test.cookie", //カレントディレクトリのtest.cookieファイルをCookieとして使用して通信
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

アクセスはできたが、圧縮されている

値は帰ってきたが文字化けしている場合です。文字エンコーディングの違いも考えられるので中身をみて判断してください。
圧縮されている場合は取得時にエンコーディングするようにオプションで設定します。

test.php
    $headers = array(
        "HTTP/1.0",
        "Accept-Encoding:gzip ,deflate",
        "Connection:keep-alive"
    );
    $curl = curl_init();
    $options = [
        CURLOPT_URL => 'URL',
        CURLOPT_CUSTOMREQUEST => 'GET',
        CURLOPT_HTTPHEADER => $headers,  
        CURLOPT_ENCODING => 'gzip',  //gzip形式でエンコーディングする
    ];
    curl_setopt_array($curl, $options);
    $response = curl_exec($curl);
    define("TESTFILE", "./TEST.txt");
    file_put_contents(TESTFILE, $response);
    curl_close($curl);

最後に

phpではfile_get_contents関数でもデータ取得が出来るのですが、curlの方がオプションが多く、扱いやすいのでオススメです。

スクレイピングで情報を抜き出す際には、対象ページの利用規約で禁止されていないか、著作権法、個人情報保護法に抵触しないか、相手のサーバに負荷をかけすぎないかなどをよく確認の上、行われた方が良いかと思います。