PHPでURL上のコンテンツを読み込む

(1/1)
PHP はファイル操作を行うこともできる。PHP が面白いのは、ローカルマシンにあるファイルと、インターネット上(URL表記)のコンテンツを同等に扱うことができる点だ。
そこで今回は、最近βテストがはじまったGoogle ニュースからリアルタイムでコンテンツを読み込み、タイトルだけ抽出して表示するプログラムを紹介する。

サンプル・プログラム

サンプル・プログラムの解説:時刻に関する注意事項

0009: <h3><?= date("n月j日G時\n") ?></h3>

関数  date  は、現在のローカル時間を扱う組み込み関数だ。
引き数に与えられたアルファベットに現在日時が対応する。たとえば、n は月の数字(ゼロを付けない)、j は日の数字(ゼロを付けない)、G は 24 時制の時の数字(ゼロを付けない)である。この他、さまざまな表示書式があるので、 関数  date  をご覧いただきたい。ここで関数 date は HTML の中に組み込まれている。

PHP プログラムを含む HTML では、<?=式 ?> のように略記法を使うことで、HTML の中で PHP の式を実行することができる。単に変数や関数の値を表示するだけなら、この略記法が便利だろう。ここで 1 つ問題がある。
関数 date は、PHP が動作しているサーバのローカル時間を返すため、もし海外のサーバでこのプログラムを動かすと、サーバのある現地時間が表示されることになる。
目的からいけば Google 日本語サイトの時間を表示させるべきなので、サーバ時間から日本標準時を計算し、表示する必要がある。通常、サーバ時間を世界標準時に変換し、それから日本標準時に変換する。
PHP には関数 date と同等で、世界標準時(グリニッジ標準時)を返す関数  gmdate  がある。そこで、date の代わりに gmdate を用い、それに 9 時間加算して日本標準時を表示させるとよい。
この部分は各自挑戦してみてほしい。

変数 $InputFile は、Google News をテキストモードで表示する URL である。この URL は変更される可能性があるので、このように変数に代入しておくのがベターだ。

変数 $Pattern は、Google News からピックアップする部分を検索するための正規検索パターンである。詳細は後で述べる。

サンプル・プログラムの解説:文字コードの扱い

0043: mb_internal_encoding('UTF-8');       //Google newsのエンコーディングはUTF-8

インターネットで日本語を使う場合、複数の文字コードがあることはご存じの通り。代表的なのは、Windows で使われている シフト JIS、UNIX 系で使われている EUC-JP、そして国際標準である UNICODE(UTF-8)など。これを間違えると、表示の文字化けを起こしたりする。
文字コードの詳しい話は「文字コードの話」をご覧いただきたい。

PHP でテキストファイルを扱う場合、まず、そのファイルの文字コードに注意する。
Google News は UTF-8 で記述されているので、 プログラムの冒頭で関数  mb_internal_encoding  を使い、内部処理で UTF-8 を使うことを宣言する。もし文字コードが EUC なら"EUC"と、UTF-8 なら"UTF-8"と記述すればよい。
PHP のマニュアルによると、シフト JIS での動作は保証していないとあるが、この程度のプログラムでは問題なく動作するようだ。(より複雑なプログラムでは、すべてのテキストを EUC-JP に変換する必要があるかもしれない)

サンプル・プログラムの解説:ファイルのオープン

0045: //ファイル・オープン
0046: if (isphp5over()) {
0047:     //PHP5以上では証明書の検証を無効化
0048:     $ctx = stream_context_create(array('ssl' => array('verify_peer' => FALSE)));
0049:     $fp = fopen($InputFile, 'r', FALSE$ctx);
0050: else {
0051:     $fp = fopen($InputFile, 'r');
0052: }
0053: //ファイルオープン・エラー
0054: if ($fp == FALSE) {
0055:     echo 'error > Google Newsを読み込めませんでした!';
0056:     exit(1);
0057: }

インターネット上のコンテンツを読み込むために、まず、関数  fopen  を使って“読み込み”オープンする必要がある。引き数は URL である。
ちなみに、PC のローカルディスクにあるファイルをオープンする場合も関数  fopen  を使う。
なお、当サイトが稼働しているサーバの都合上、証明書の検証を無効化している。

正常にファイルがオープンできると、関数  fopen  はリソース番号を返す。今後、このファイルへのアクセスはリソース番号を介して行うことになるので、リソース番号を変数 $fp に保存しておく。
関数  fopen  はエラーを発生する場合がある。たとえば、引き数に指定されたファイルがない場合(HTTP サーバの 404 エラー)などだ。そこで、エラー対処も記述しておく。
関数  fopen  は、エラー発生時に FALSE を返す。もし変数$fp が FALSE だったら、エラー表示を行い、関数  exit  によってプログラムを強制終了する。

サンプル・プログラムの解説:ファイルを読んで記事見出しを抽出する

0058: //コンテンツを1行ずつ読み込んで処理する
0059: while (! feof($fp)) {
0060:     $s = fgets($fp);
0061:     $n = preg_match_all($Pattern$s$arPREG_SET_ORDER);
0062:     //マッチングしたすべての箇所を表示する
0063:     for ($i = 0; $i < $n$i++)     echo '' . $ar[$i][2] . "<br />\n";
0064: }

テキストファイルを 1行読み込むのは、関数  fgets  である。引き数は fopen関数で取得したりソース番号 $fp だ。
読み込んだ 1行は、変数 $s に代入する。

このプログラムの目的は、Google News から記事見出しのみ抽出することである。
読み込んだ行には複数の見出しが含まれているが、各々は事前に設定した正規表現パターン $Pattern を有する。(これは筆者が独自に調べたもので、今後変更される可能性はある)
そこで、読み込んだ行 $s に含まれるすべての見出しパターンを抽出するために、関数  preg_match_all  を使う。
関数  preg_match_all  は、引き数の正規表現パターンに合致するすべての部分文字列を配列に格納し、合致した部分文字列の数を返す。
合致した部分文字列とは、すなわち記事見出しである。そこで、逐次、部分文字列を表示させることでプログラムの目的を達する。この作業をテキストファイルの終わりまで繰り返す。
正規表現については、「PHP で正規表現」をあわせてご覧いただきたい。

関数  feof  は、ファイルの終端まで来たら TRUE を、そうでなければ FALSE を返す。ここでは否定演算子 ! を付けて、ファイル終端に到達するまで while ループを回し、ファイルを読んで記事見出しを抽出・表示させる処理を続ける、という形になる。

ファイルを閉じる

0065: //ファイル・クローズ
0066: fclose($fp);
0067: 
0068: // ここまでPHPプログラム =======================================================
0069: ?>
0070: 
0071: <p><img src="http://www.google.co.jp/logos/powered_by_google_135x35.gif" /></p>

fopen関数で閉じたファイルは、最後に、関数  fclose  によって閉じなければならない。
最後に、お世話になった Google のロゴを表示しておこう。

質疑応答

【質問】 smily 様より

実際に「プログラムを実行する」をしたのですが、検索結果が 0 件で、Google news よりと、システム日付、ロゴしか表示されません。
デバックしていくと、
$n = preg_match_all($Pattern, $s, $ar, PREG_SET_ORDER);
の部分で、結果が 0 件になっているようなのですが、それが原因でしょうか。正規表現にマッチするものがないのでしょうか。
お忙しいところお手数ですが、解決方法をご教授願えますでしょうか。
ちなみに環境としましては、PHP5、Apache2.2 を使用しております。


【回答】

プログラムが古く、最近の GoogleNews に対応していませんでした。
「サンプル・プログラムの解説」でも述べたように、正規表現パターンが変わっていたことと、GoogleNews自体の文字コードがシフト JIS から UTF-8 に変更されていました。
そこで、最新の GoogleNews を読み込めるようにプログラムを修正したので、どうぞお試しください。

参考サイト

(この項おわり)
header