cURL は、URL 構文を使用してファイルやデータを転送するツールで、HTTP、FTP、TELNET などの多くのプロトコルをサポートします。最も優れた点は、php が cURL ライブラリもサポートしていることです。この記事では、cURL の高度な機能と、それを PHP で使用する方法を紹介します。
cURL を使用する理由
はい、他の方法でも Web コンテンツを取得できます。ほとんどの場合、私は怠惰になりたいので、単純な php 関数を使用するだけです。
$content = file_get_contents(" http://www.bizhicool.com ");
// または
$lines = file(" http://www.bizhicool.com ");
// または
readfile( http://www.bizhicool.com ); ただし、このアプローチには柔軟性と効果的なエラー処理が欠けています。さらに、Cookie の処理、検証、フォームの送信、ファイルのアップロードなど、いくつかの難しいタスクを完了するために使用することはできません。
cURL は、さまざまなプロトコルやオプションをサポートし、URL リクエストに関連するさまざまな詳細を提供できる強力なライブラリです。
基本構造 より複雑な関数について学ぶ前に、PHP で cURL リクエストを設定する基本的な手順を見てみましょう。
初期化、変数の設定、実行と結果の取得、cURL ハンドルの解放
// 1. 初期化
$ch =curl_init();
// 2. URL を含むオプションを設定します
curl_setopt($ch, CURLOPT_URL, " http://www.bizhicool.com ");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
// 3. HTML ドキュメントを実行してコンテンツを取得します
$output =curl_exec($ch);
// 4. カールハンドルを解放します
curl_close($ch); 2 番目のステップ (つまり、curl_setopt()) が最も重要であり、すべての謎はここにあります。 URL リクエストのさまざまな詳細を指定する、設定できる cURL パラメーターの長いリストがあります。これらをすべて一度に読んで理解するのは難しい場合があるため、今日はより一般的で便利なオプションのみを試します。
エラーのチェック エラーをチェックするステートメントを追加できます (ただし、これは必須ではありません)。
// ...
$output =curl_exec($ch);
if ($output === FALSE) {
echo "cURL エラー: " .curl_error($ch);
}
// ...比較する際には、「== FALSE」ではなく「=== FALSE」を使用することに注意してください。空の出力とブール値 FALSE (実際のエラー) を区別する必要があるためです。
情報の取得 これは、cURL の実行後にこのリクエストに関する情報を取得できる別のオプションの設定です。
// ...
curl_exec($ch);
$info =curl_getinfo($ch);
echo 'Get'. $info['url'] '時間がかかります'。
// ...返される配列には次の情報が含まれます。
"url" //リソースネットワークアドレス
"content_type" //コンテンツのエンコーディング
"http_code" //HTTPステータスコード
"header_size" //ヘッダーのサイズ
"request_size" //リクエストサイズ
"filetime" //ファイルの作成時間
"ssl_verify_result" //SSL検証結果
"redirect_count" //ジャンプテクノロジー
"total_time" //かかった合計時間
"namelookup_time" //DNS クエリ時間
"connect_time" //接続時間の待機
"pretransfer_time" //送信前の準備時間
"size_upload" //アップロードされたデータのサイズ
"size_download" //ダウンロードしたデータのサイズ
"speed_download" //ダウンロード速度
"speed_upload" //アップロード速度
"download_content_length" //ダウンロード コンテンツの長さ
"upload_content_length" //アップロードされたコンテンツの長さ
"starttransfer_time" //転送を開始する時間
"redirect_time" //リダイレクトには時間がかかります ブラウザベースのリダイレクト 最初の例では、サーバーにブラウザベースのリダイレクトがあるかどうかを検出するコードを提供します。たとえば、一部の Web サイトは、モバイル ブラウザであるかどうか、さらにはユーザーの出身国に基づいて Web ページをリダイレクトします。
CURLOPT_HTTPHEADER オプションを使用して、ユーザー エージェント情報やデフォルト言語など、送信する HTTP リクエスト ヘッダー (http ヘッダー) を設定します。次に、これらの特定の Web サイトが別の URL にリダイレクトするかどうかを確認します。
// テスト用のURL
$urls = 配列(
「 http://www.cnn.com 」、
「 http://www.mozilla.com 」、
「 http://www.facebook.com 」
);
// テスト用のブラウザ情報
$ブラウザ = 配列(
"標準" => 配列 (
"user_agent" => "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 (.NET CLR 3.5.30729)",
"言語" => "en-us,en;q=0.5"
)、
"iphone" => 配列 (
"user_agent" => "Mozilla/5.0 (iPhone; U; Mac OS X のような CPU; en) AppleWebKit/420+ (Gecko のような KHTML) バージョン/3.0 Mobile/1A537a Safari/419.3",
「言語」=>「英語」
)、
"フランス語" => 配列 (
"user_agent" => "Mozilla/4.0 (互換性; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 2.0.50727)",
"言語" => "fr,fr-FR;q=0.5"
)
);
foreach ($urls として $url) {
echo "URL: $urln";
foreach ($browsers as $test_name => $browser) {
$ch =curl_init();
//URLを設定
curl_setopt($ch, CURLOPT_URL, $url);
// ブラウザ固有のヘッダーを設定します
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"ユーザーエージェント: {$browser['user_agent']}",
"Accept-Language: {$browser[' language']}"
));
// ページのコンテンツは必要ありません
curl_setopt($ch, CURLOPT_NOBODY, 1);
// HTTP ヘッダーを返すだけです
curl_setopt($ch, CURLOPT_HEADER, 1);
// 結果を印刷する代わりに返します
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output =curl_exec($ch);
カール_クローズ($ch);
// リダイレクト用の HTTP ヘッダー情報はありますか?
if (preg_match("!場所: (.*)!", $output, $matches)) {
echo "$test_name: $matches[1] にリダイレクトしますn";
} それ以外 {
echo "$test_name: リダイレクトなしn";
}
}
エコー「nn」;
}まず、テストする必要がある URL のセットを作成し、次にテストする必要があるブラウザ情報のセットを指定します。最後に、ループを使用して、発生する可能性のあるさまざまな URL とブラウザの一致状況をテストします。
cURL オプションを指定したため、返される出力には HTTP ヘッダー情報 ($output に格納) のみが含まれます。単純な規則ルールを使用して、ヘッダー情報に「Location:」という単語が含まれているかどうかを確認します。
このコードを実行すると、次の結果が返されるはずです。
POST メソッドを使用したデータの送信 GET リクエストを行う場合、「クエリ文字列」を介してデータを URL に渡すことができます。たとえば、Google で検索する場合、検索キーは URL のクエリ文字列の一部になります。
http://www.google.com/search?q=nettutsこの場合、おそらく cURL をシミュレートする必要はありません。この URL を「file_get_contents()」にスローすると、同じ結果が得られます。
ただし、一部の HTML フォームは POST メソッドを使用して送信されます。このフォームが送信されると、データはクエリ文字列ではなく HTTP リクエスト本文 (リクエストボディ) を通じて送信されます。たとえば、CodeIgniter フォーラム フォームを使用する場合、どのようなキーワードを入力しても、常に次のページに POST されます。
http://codeigniter.com/forums/do_search/ PHP スクリプトを使用して、この URL リクエストをシミュレートできます。まず、POST データを受け入れて表示できる新しいファイルを作成し、post_output.php という名前を付けます。
print_r($_POST); 次に、cURL リクエストを実行する PHP スクリプトを作成します。
$url = " http://localhost/post_output.php ";
$post_data = 配列 (
"foo" => "バー",
"クエリ" => "ネットッツ",
「アクション」=>「送信」
);
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// データを POST しています!
curl_setopt($ch, CURLOPT_POST, 1);
//ポスト変数を追加します
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$output =curl_exec($ch);
カール_クローズ($ch);
echo $output;コードを実行すると、次の結果が得られます。
このスクリプトは、POST リクエストを post_output.php (ページの $_POST 変数) に送信し、cURL を使用してこの出力をキャプチャします。
ファイルのアップロード ファイルのアップロードは、前の POST と非常に似ています。すべてのファイル アップロード フォームは POST メソッドを通じて送信されるためです。
まず、ファイルを受信するための新しいページ (upload_output.php という名前) を作成します。
print_r($_FILES);以下は、ファイル アップロード タスクを実際に実行するスクリプトです。
$url = " http://localhost/upload_output.php ";
$post_data = 配列 (
"foo" => "バー",
//アップロードするローカルファイルアドレス
「アップロード」 => 「@C:/wamp/www/test.zip」
);
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$output =curl_exec($ch);
カール_クローズ($ch);
echo $output; ファイルをアップロードする必要がある場合は、post 変数のようにファイル パスを渡すだけですが、先頭に @ 記号を追加することを忘れないでください。このスクリプトを実行すると、次の出力が得られます。
cURL バッチ処理 (マルチ cURL)
cURL には、バッチ ハンドルという高度な機能もあります。この機能を使用すると、複数の URL 接続を同時にまたは非同期で開くことができます。
php.net のサンプルコードは次のとおりです。
// 2 つの cURL リソースを作成します
$ch1 =curl_init();
$ch2 =curl_init();
// URL と適切なパラメータを指定します
curl_setopt($ch1, CURLOPT_URL, " http://lxr.php.net/ ");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, " http://www.php.net/ ");
curl_setopt($ch2, CURLOPT_HEADER, 0);
//cURLバッチハンドルを作成
$mh =curl_multi_init();
//最初の 2 つのリソース ハンドルを追加します
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
// 状態変数を事前定義します
$active = null;
//バッチ処理を実行する
する {
$mrc =curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
する {
$mrc =curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//各ハンドルを閉じる
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh); ここで行う必要があるのは、複数の cURL ハンドルを開いて、それらをバッチ ハンドルに割り当てることです。次に、while ループで完了するまで待つだけです。
この例には 2 つの主要なループがあります。最初の do-while ループは、curl_multi_exec() を繰り返し呼び出します。この関数はノンブロッキングですが、実行される回数は最小限に抑えられます。ステータス値を返します。この値が定数 CURLM_CALL_MULTI_PERFORM と等しい限り、実行すべき緊急の作業がまだあることを意味します (たとえば、URL に対応する http ヘッダー情報の送信)。つまり、戻り値が変わるまでこの関数を呼び出し続ける必要があります。
次の while ループは、$active 変数が true の場合にのみ続行されます。この変数は以前に 2 番目のパラメータとしてcurl_multi_exec() に渡されており、バッチ ハンドルにアクティブな接続がまだ存在するかどうかを表します。次に、curl_multi_select() を呼び出します。これは、アクティブな接続 (サーバー応答の受信など) が発生するまで「ブロック」されます。この関数が正常に実行された後、別の do-while ループに入り、次の URL に進みます。
この機能を実際に活用する方法を見てみましょう。
WordPress 接続チェッカー 外部 Web サイトへのリンクを多数含む記事が多数あるブログがあると想像してください。しばらくすると、これらのリンクのかなりの数が何らかの理由で無効になりました。調和されているか、サイト全体がハッキングされているかのどちらかです...
これらすべてのリンクを分析し、開けない Web サイトや Web ページ、または 404 が発生している Web サイト/Web ページを見つけて、レポートを生成する以下のスクリプトを作成しましょう。
以下は実際に動作する WordPress プラグインではなく、デモンストレーションのみを目的とした、独立した機能を備えた単なるスクリプトであることに注意してください。ありがとうございます。
はい、始めましょう。まず、データベースからこれらのリンクをすべて読み取ります。
//設定
$db_host = 'ローカルホスト';
$db_user = 'ルート';
$db_pass = '';
$db_name = 'ワードプレス';
$excluded_domains = array(
'localhost'、'www.mydomain.com');
$max_connections = 10;
//いくつかの変数を初期化します
$url_list = 配列();
$working_urls = array();
$dead_urls = 配列();
$not_found_urls = array();
$active = null;
// MySQLに接続します
if (!mysql_connect($db_host, $db_user, $db_pass)) {
die('接続できませんでした: ' .mysql_error());
}
if (!mysql_select_db($db_name)) {
die('データベースを選択できませんでした: ' .mysql_error());
}
// リンクのあるすべての記事を検索します
$q = "wp_posts から post_content を選択
WHERE post_content LIKE '%href=%'
かつ post_status = '公開'
かつ post_type = 'post'";
$r = mysql_query($q) または die(mysql_error());
while ($d = mysql_fetch_assoc($r)) {
// 通常の一致リンクを使用する
if (preg_match_all("!href="(.*?)"!", $d['post_content'], $matches)) {
foreach ($matches[1] as $url) {
// 一部のドメインを除外します
$tmp = parse_url($url);
if (in_array($tmp['host'], $excluded_domains)) {
続く;
}
// URLを保存
$url_list []= $url;
}
}
}
// 重複したリンクを削除します
$url_list = array_values(array_unique($url_list));
if (!$url_list) {
die('チェックする URL がありません');
}最初にデータベース、除外する一連のドメイン名 ($excluded_domains)、および同時接続の最大数 ($max_connections) を構成します。次に、データベースに接続し、記事と含まれるリンクを取得し、それらを配列 ($url_list) に収集します。
以下のコードは少し複雑なので、ステップごとに詳しく説明します。
// 1. バッチプロセッサ
$mh =curl_multi_init();
// 2. バッチで処理する必要がある URL を追加します
for ($i = 0; $i < $max_connections; $i++) {
add_url_to_multi_handle($mh, $url_list);
}
// 3. 初期処理
する {
$mrc =curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
// 4. メインループ
while ($active && $mrc == CURLM_OK) {
// 5. アクティブな接続があります
if (curl_multi_select($mh) != -1) {
// 6. 作業
する {
$mrc =curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
// 7. 何か情報はありますか?
if ($mhinfo =curl_multi_info_read($mh)) {
//接続が正常に終了したことを意味します
// 8.カールハンドルから情報を取得します
$chinfo =curl_getinfo($mhinfo['ハンドル']);
// 9. デッドリンク?
if (!$chinfo['http_code']) {
$dead_urls []= $chinfo['url'];
// 10.404?
} else if ($chinfo['http_code'] == 404) {
$not_found_urls []= $chinfo['url'];
// 11. まだ利用可能です
} それ以外 {
$working_urls []= $chinfo['url'];
}
// 12. ハンドルを削除します
curl_multi_remove_handle($mh, $mhinfo['handle']);
curl_close($mhinfo['ハンドル']);
// 13. 新しい URL を追加して作業を実行します
if (add_url_to_multi_handle($mh, $url_list)) {
する {
$mrc =curl_multi_exec($mh, $active);
while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
}
}
// 14. 完了
curl_multi_close($mh);
echo "==無効な URL==n";
echo implode("n",$dead_urls) 。
echo "==404 URLs==n";
echo implode("n",$not_found_urls) "nn";
echo "==作業中の URL==n";
echo implode("n",$working_urls);
// 15. URLをバッチプロセッサに追加します
関数 add_url_to_multi_handle($mh, $url_list) {
静的 $index = 0;
// URLが残ってもダメ
if ($url_list[$index]) {
// 新しいカールハンドルを作成します
$ch =curl_init();
//URLを設定する
curl_setopt($ch, CURLOPT_URL, $url_list[$index]);
// 返された内容を出力したくない
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// リダイレクトされた場所ならどこへでも行きます
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// コンテンツ本文は必要ないため、帯域幅と時間を節約できます
curl_setopt($ch, CURLOPT_NOBODY, 1);
//バッチプロセッサに追加
curl_multi_add_handle($mh, $ch);
// カウンターにダイヤルすると、次回この関数を呼び出すときに次の URL を追加できます。
$インデックス++;
true を返します。
} それ以外 {
// 新しい URL を処理する必要はありません
false を返します。
}
上記のコードを以下で説明します。リスト内のシリアル番号は、コード コメント内の連続番号に対応します。
新しいバッチ プロセッサを作成します。マルチハンドルを作成しました。
後で、URL をバッチ ハンドラーに追加する関数 add_url_to_multi_handle() を作成します。この関数が呼び出されるたびに、新しい URL がバッチ プロセッサに追加されます。最初に、10 個の URL をバッチ プロセッサに追加します (この数は $max_connections によって決まります)。
初期化作業を行うには、curl_multi_exec() を実行する必要があります。CURLM_CALL_MULTI_PERFORM が返される限り、まだやるべきことが残っています。これは主に接続を作成するために行われ、完全な URL 応答を待ちません。
メイン ループは、バッチ内にアクティブな接続がある限り継続します。
curl_multi_select() は、URL クエリの結果、アクティブな接続が確立されるまで待機します。
cURL の役割は、主に応答データを取得することです。
さまざまな情報を確認してください。 URL リクエストが完了すると、配列が返されます。
返された配列には cURL ハンドルがあります。これを使用して、単一の cURL リクエストに対応する情報を取得します。
これがデッドリンクであるか、リクエストがタイムアウトした場合、http ステータス コードは返されません。
このページが見つからない場合は、404 ステータス コードが返されます。
それ以外の場合は、このリンクが利用可能であると想定します (もちろん、500 エラーなどを確認することもできます...)。
この cURL ハンドルはもう使用されないのでバッチから削除し、閉じてください。
わかりました。別の URL を追加できるようになりました。再び初期化作業が始まります…。
さて、やるべきことはすべて完了しました。バッチ プロセッサを閉じて、レポートを生成します。
新しい URL をバッチ プロセッサに追加する関数に戻りましょう。この関数が呼び出されるたびに、静的変数 $index がインクリメントされるため、処理すべき URL がいくつ残っているかがわかります。
このスクリプトを自分のブログで実行しました (テストの必要があり、いくつかの間違ったリンクが意図的に追加されています)。結果は次のとおりです。
合計約 40 の URL がチェックされましたが、所要時間は 2 秒もかかりませんでした。より多くの URL をチェックする必要がある場合、その心配を軽減する効果は想像できます。 10 個の接続を同時に開くと、速度は 10 倍になります。さらに、cURL バッチ処理のノンブロッキング機能を利用して、Web スクリプトをブロックせずに大量の URL リクエストを処理することもできます。
その他の便利な cURL オプション
HTTP 認証 URL リクエストに HTTP ベースの認証が必要な場合は、次のコードを使用できます。
$url = " http://www.somesite.com/members/ ";
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// ユーザー名とパスワードを送信する
curl_setopt($ch, CURLOPT_USERPWD, "myusername:mypassword");
// リダイレクトを許可できます
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// 次のオプションにより、cURL は
// ユーザー名とパスワードも送信できます
curl_setopt($ch, CURLOPT_UNRESTRICTED_AUTH, 1);
$output =curl_exec($ch);
curl_close($ch);FTP アップロード
PHP には独自の FTP ライブラリが付属していますが、cURL を使用することもできます。
// ファイルポインタを開く
$file = fopen("/ファイルへのパス", "r");
// URL には必要な情報のほとんどが含まれています
$url = " ftp://ユーザー名:パスワード@mydomain.com:21/path/to/new/file ";
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//アップロード関連のオプション
curl_setopt($ch, CURLOPT_UPLOAD, 1);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize("/path/to/file"));
// ASCII モードを有効にするかどうか (テキスト ファイルをアップロードするときに役立ちます)
curl_setopt($ch, CURLOPT_FTPASCII, 1);
$output =curl_exec($ch);
curl_close($ch); この壁を回避するには、プロキシを使用して cURL リクエストを開始します。
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL,'http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//プロキシアドレスを指定
curl_setopt($ch, CURLOPT_PROXY, '11.11.11.11:8080');
// 必要に応じてユーザー名とパスワードを入力します
curl_setopt($ch, CURLOPT_PROXYUSERPWD,'user:pass');
$output =curl_exec($ch);
curl_close ($ch); コールバック関数を使用すると、cURL は URL リクエスト中に指定されたコールバック関数を呼び出すことができます。たとえば、コンテンツまたは応答がダウンロードされたら、完全にダウンロードされるまで待つのではなく、すぐにデータの利用を開始します。
$ch =curl_init();
curl_setopt($ch, CURLOPT_URL,'http://net.tutsplus.com');
curl_setopt($ch, CURLOPT_WRITEFUNCTION,"progress_function");
curl_exec($ch);
カール_クローズ ($ch);
関数 progress_function($ch,$str) {
エコー $str;
strlen($str) を返します。
}このコールバック関数は文字列の長さを返す必要があります。そうでない場合、この関数は正しく動作しません。
URL 応答受信処理中、データ パケットを受信している限りこの関数が呼び出されます。
まとめ 今日は、cURL ライブラリの強力な機能と柔軟な拡張性について学びました。気に入っていただければ幸いです。次回 URL リクエストを行う場合は、cURL を検討してください。
ありがとう!
原文: PHP ベースの cURL のクイック スタート
英語原文: http://net.tutsplus.com/tutorials/php/techniques-and-resources-for-mastering-curl/
原作者:ブラク・ギュゼル
転載する場合は出典を保管しなければなりません。