PHP
Guzzle
crawler

Guzzleの基本的なリクエストオプション設定まとめ

環境

  • PHP 7.2.0
  • Guzzle 6.3

HTTPステータスが4xx、5xxの場合に例外を出さないようにする

  • 例外を抑制するためには、リクエストオプションに「http_errors => false」を指定します。
  • デフォルトはtrueのため、例えば404エラーの場合に例外が発生します。
  • ただし、ホストに接続できない場合はこれに関係なくConnectExceptionが発生します。
test1.php
    $client = new GuzzleHttp\Client();
    $res = $client->request("GET", "https://qiita.com/f/o/o/tnm18", array(
        "http_errors" => false,
    ));
    var_dump($res->getStatusCode());  // => int(404)

Cookieを使用する

  • Cookieはデフォルトで無効なため、自分で指定する必要があります。
  • Cookieを有効するには、CookieJarのインスタンスをリクエストオプションの「cookies」に設定します。
  • 以下はniconicoにログインしてマイページにアクセスする例です。
test2.php
    $jar = new GuzzleHttp\Cookie\CookieJar();

    // ログイン処理
    $client = new GuzzleHttp\Client();
    $res = $client->request("POST", "https://account.nicovideo.jp/api/v1/login", array(
        "cookies" => $jar,
        "form_params" => array(
            "mail_tel" => "****@****.com",
            "password" => "****",
        ),
    ));

    // Cookieを使用してマイページを取得
    $res = $client->request("GET", "http://www.nicovideo.jp/my/top", array(
        "cookies" => $jar,
    ));

    if(preg_match("/<title>(.*?)<\/title>/i", $res->getBody(), $m)){
        var_dump($m[1]);  // => string(45) "マイページ 最新ニコレポ - niconico"
    }

リクエストヘッダーを設定する

  • User-AgentやAcceptなどのリクエストヘッダーを設定するには、リクエストオプションの「headers」を指定します。
test3.php
    $client = new GuzzleHttp\Client();
    $res = $client->request('GET', 'https://qiita.com/tnm18', array(
        "headers" => array(
            "User-Agent" => "myapp/1.0.0",
        ),
    ));

リクエストボディを設定する

  • API等でリクエスト時にBodyを送信する場合は、リクエストオプションの「body」を設定します。
  • Bodyには文字列の他にfopen()でファイルパスやURLも指定できます。
test4.php
    $client = new GuzzleHttp\Client();
    $res = $client->request('GET', 'https://qiita.com/tnm18', array(
        "body" => "foo",
        // "body" => fopen("/path/to/file", "r"),
    ));

タイムアウトを設定する

  • リクエストのタイムアウトは、リクエストオプションの「connect_timeout」と「timeout」にfloatで「秒」を指定します。
  • デフォルトのタイムアウトは0(無制限)です。
  • タイムアウトした場合は、ConnectExceptionが発生します。
test5.php
    $client = new GuzzleHttp\Client();
    $res = $client->request("GET", "https://qiita.com/tnm18", array(
        "connect_timeout" => 0.01,  // <= サーバーへの接続を0.01秒まで待機
        "timeout" => 0.01,  // <= レスポンスを0.01秒まで待機
    ));
    // => ConnectException

ディレイを設定する

  • 同じドメインへ連続アクセスする場合はディレイを設けないと接続先サーバーに負荷がかかり、HTTP429になったりします。
  • ディレイはリクエストオプションの「delay」にfloatで「ミリ秒」を指定します。デフォルトは0(ディレイなし)
  • これは、指定した時間だけ待機した後にリクエストを送信するという動きになります。
test6.php
    $client = new GuzzleHttp\Client();
    $res = $client->request("GET", "https://qiita.com/tnm18", array(
        "delay" => 5000.0,  // <= ディレイ5秒
    ));
    var_dump($res->getStatusCode());

レスポンスボディをファイルに保存する

  • リクエストオプションの「sink」にファイルパスまたはリソースを指定することで、応答本文をファイルに保存できます。
  • ただし、リクエストに失敗した場合もファイルは作成されます。
test7.php
    $rsc = fopen(__DIR__. "/out.html", "w");
    $client = new GuzzleHttp\Client();
    $client->request('GET', 'https://qiita.com/tnm18', array(
        "sink" => $rsc,
    ));

転送時の進捗状況を取得する

  • リクエストオプションの「progress」にコールバック関数を渡すと、進捗状況が取得できます。
  • 動画ファイルのDL等に有効ですが、転送量が小さいとTotalが0になるようです。
test8.php
    $client = new GuzzleHttp\Client();
    $res = $client->request("GET", "https://qiita.com/tnm18", array(
        "progress" => function( 
            $downloadTotal,    // ダウンロードが予想される合計バイト数
            $downloadedBytes,  // これまでにダウンロードされたバイト数
            $uploadTotal,      // アップロードされる予定の合計バイト数
            $uploadedBytes     // これまでにアップロードされたバイト数
        ){
            // 進捗上京の表示処理
        })
    );
    var_dump($res->getStatusCode());

他にもSSLやProxyの設定など、リクエストに関する様々なオプションがあります。
参考:https://github.com/guzzle/guzzle/blob/master/docs/request-options.rst