質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

4737閲覧

PHP file_get_contentsで複数のサイトのコンテンツから要素を取得する場合

pegy

総合スコア243

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/07/23 07:32

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mpyw

2016/07/23 11:35

もとからそこそこのPVを捌いているようなサイトであれば,5秒ごとぐらいでも普通は何の迷惑にもならないですね.(この発言に関して責任は取りません
pegy

2016/07/23 12:22

ご回答有難うございます。 飽くまで自己責任で対応させていただきます。
pegy

2016/07/23 12:38

因みにですが、sleepを設定せずにループさせた場合、デフォルトでは何秒の設定になるものなのでしょうか。 重ねて失礼致します。
mpyw

2016/07/23 19:53

(通信遅延を除けば)0秒ですね.
takasima20

2016/07/23 20:54

横から失礼します。 HEADリクエストを返さないサーバーがある みたいなことを聞いた気がするのですが、 実際のとこどうなんでしょう?
mpyw

2016/07/24 04:49

あ,動的なコンテンツとして実装されている場合は確かにあり得ます.例えばPHPで $_SERVER['REQUEST_METHOD'] === 'GET' とかやってる場合ですね.今回の場合は相手サーバが1つなので,最初に1回HEADリクエストを飛ばしてみて,通るかどうか確認すれば使っても良さそうです.
mpyw

2016/07/24 05:04 編集

ただ,GETには応答するのに同じ内容のHEADで400以上を返すのは,RFCに違反していそう…という疑問はあります.
takasima20

2016/07/24 05:44

ありがとうございます。なるほどですねえ。
guest

0

file_get_contents の結果に false が返っていると思うのでそれをスキップする処理をすればよいです。

ただ、このスクリプト、同一のサーバに対して実施する予定ですよね?
API を探されるか、サーバ管理者に許可をもらうか、サーバに負荷をかけないようにアクセスに間を空けるかしなければいけません。

投稿2016/07/23 08:43

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2016/07/23 08:51

ご回答頂き有難うございます。コードについてはよくわかりました。有難うございます。 対象ページは約2000程度なんですが、サーバーへのアクセスは1度だけです。 サーバーに負荷かかかり、ご迷惑をおかけする可能性は存じ上げておりましたが、どの程度で負担になるか目安等があればご教示願えますでしょうか? 例えば、ページ数とアクセス回数のいずれが問題になるかも存じ上げず、お願い致します。 また、ここでいう、APIとは具体的にどの様なものかご教示願えますでしょうか?よろしくお願い申し上げます。
退会済みユーザー

退会済みユーザー

2016/07/23 09:23

サーバへのアクセスが1度だけという意味がよく分かりませんが、少なくとも、2000回はアクセスするのではないですか? 許容される負荷に関しては一般的なものはありません。 余り負荷に強くないシステムであれば、あなたのアクセスでサービスが停止する可能性があります。過去にはサービス停止で逮捕された例もあります。 そのため、事前にサーバ管理者へ問い合わせが必要です。 また、ここで言うAPIは「ウェブAPI」のことです。下記を参考にして下さい。 https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9#.E3.82.A6.E3.82.A7.E3.83.96API
pegy

2016/07/23 09:36

ご回答有難うございます。 大変勉強になりました。 確認を致します。よろしくお願い申し上げます。
guest

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
takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2016/07/23 12:27

ご回答有難うございます。 実行する前に有効であるか否かを2000ページ分確認してすることは可能なのでしょうか?全てget_file_contentsでurlが存在するか(trueか)を確認するだけで負荷をかけてしまいそうで恐いのですが。 もし違う方法をイメージしていらっしゃるのであればご教示頂ければ幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問