PHPのfile_get_contentsを使用し、一部の情報を取得したいと考えております。そこでコンテンツを取得するサイトですが、複数のページに分かれており
"http://XXXX/1.html";
"http://XXXX/2.html";
.
.
.
.
"http://XXXX/10.html";
となっているのですが、途中で
"http://XXXX/7.html";
"http://XXXX/9.html";
が存在しておりません。
以上の前提から、for文を使ってループ処理を行いたいのですが、
"http://XXXX/7.html";
"http://XXXX/9.html";
が存在しないために、プログラム自体がエラーとなってしまいます。
もし、urlが存在しない場合、する場合に分けてif文を使用しながら
ループさせるかと思うのですが、具体的な方法が思いつかないため、
お知恵をお借りしたく投稿させていただきました。
よろしくお願い申し上げます。
<?php $max =10; for ($i = 1; $i <=$max; ++$i) { $url= "http://XXXX/".$i.".html"; $file = file_get_contents($url); (省略)要素取得の実行
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
cURL関数群を使う方法のほうがおすすめです.
- file_get_contentsよりもエラーハンドリングの方法がキッチリしている
(file_get_contentsは失敗するとWarningが発生して不格好)
- **HTTP/1.1のKeep-Aliveにより,同じ接続先であればTCPコネクションを再利用できる
(file_get_contentsはHTTP/1.0で毎回TCPコネクションを生成する古臭い方法を使っている)**
- 通信の自動的な圧縮と伸張ができる
php
1$ch = curl_init(); 2curl_setopt_array($ch, [ 3 CURLOPT_RETURNTRANSFER => true, // 結果を文字列で返す 4 CURLOPT_ENCODING => 'gzip', // 通信を自動的に圧縮・伸張する 5 CURLOPT_FAILONERROR => true, // 400以上のステータスコードもfile_get_contentsのようにエラー扱いにする (ただしWarningは出さない), 6 CURLOPT_FOLLOWLOCATION => true, // Locationヘッダを自動で追跡する 7]); 8 9for ($i = 1; $i <= 2000; ++$i) { 10 // URLを設定 11 curl_setopt($ch, CURLOPT_URL, "http://example.com/$i"); 12 // コンテンツの取得を試みる 13 $response = curl_exec($ch); 14 if ($response === false) { 15 $reason = curl_error($ch); // エラーメッセージを取得して何かするならやる 16 var_dump($reason); 17 continue; 18 } 19 var_dump($response); 20 sleep(15); // 必須 21}
15秒という数字には何の根拠もありませんが,かなり余裕を持って設定した「よほどアホなプログラマが作ったシステムじゃなければ普通は迷惑にならない」と判断できる数字です.主観なので,これによってトラブルが発生しても私は責任をとりません.最低限,利用規約をよく読んで禁止事項がないか確認してから行うべきです.
ちなみに逮捕者が出た例の図書館の事件では,1秒ごとにリクエストを行っていました.正直1秒ごとでもまともなシステムならびくともしないはずなんですが,バグのある低品質なプロダクトが納品されていたのが原因の1つで,かつ図書館側にもIT業界の人間からすればかなり横暴に思えてしまう対応が為され,逮捕者が出る悲劇に繋がってしまったようです.
【補足】
「ページが有効かどうか」のみを調べたい場合,HEADリクエストを送るのが正解です.これが最も効率が良く,サーバにも負荷をかけない方法です. (「GETで1バイトだけ受信する」という方法はあまりお行儀が良くないです)
php
1$ch = curl_init(); 2curl_setopt_array($ch, [ 3 CURLOPT_FOLLOWLOCATION => true, // Locationヘッダを自動で追跡する 4 CURLOPT_NOBODY => true, // GETリクエストの代わりにHEADリクエストを送る (HTMLを取得しない), 5]); 6 7for ($i = 1; $i <= 2000; ++$i) { 8 if ($i !== 1) sleep(15); 9 curl_setopt($ch, CURLOPT_URL, "http://example.com/$i"); 10 $result = curl_exec($ch); 11 $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 12 if ($result === false || $code >= 500) { 13 // 通信障害,またはサーバが不調 14 continue; 15 } 16 if ($code === 404) { 17 // コンテンツが見つからない 18 continue; 19 } 20 if ($code >= 400) { 21 // 何かしら問題のあるアクセスをしている 22 continue; 23 } 24 // ほぼ成功と考えていい 25}
投稿2016/07/23 11:28
編集2016/07/23 20:04総合スコア5223
0
file_get_contents の結果に false が返っていると思うのでそれをスキップする処理をすればよいです。
ただ、このスクリプト、同一のサーバに対して実施する予定ですよね?
API を探されるか、サーバ管理者に許可をもらうか、サーバに負荷をかけないようにアクセスに間を空けるかしなければいけません。
投稿2016/07/23 08:43
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/07/23 09:23
2016/07/23 09:36
0
ベストアンサー
ちょっとずれた話になりますが…
(1) URL候補リスト作成
(2) 上記を元に有効URLリスト作成
(3) 上記を元に想定内のフォーマットかチェック
(4) 上記を元に情報取得
自分だったらこんな感じに作業すると思います。
対象サーバーに負担をかけないよう(何度も全件やり直しをしないよう)
慎重にやるのは当然ですが、それでもイリーガルなことはえてして
起きてしまうものです。準備はやりすぎるということはないでしょう。
--- 追加 ---
できるかどうかではなく、そうした方がいいんじゃないの?
って話です。もちろん、そうあるべきって話じゃないです。
PHP
1$url = 'http://XXXX/1.html'; 2$res = @file_get_contents($url, NULL, NULL, 0, 1); 3if ($res !== false) { 4 // 存在した時の処理 5} else { 6 // 存在しない時の処理 7}
例えば上のように1バイトだけ要求するならば
最低限の負荷で確認できるような気がします。
もちろん、だからといって連続でリクエストを
投げるのは論外ですけどね。
投稿2016/07/23 12:04
編集2016/07/23 12:41総合スコア7458
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/07/23 11:35
2016/07/23 12:22
2016/07/23 12:38
2016/07/23 19:53
2016/07/23 20:54
2016/07/24 04:49
2016/07/24 05:04 編集
2016/07/24 05:44