目次
サンプル・プログラムの実行例

サンプル・プログラム
解説:時刻に関する注意事項
0008: <h2>ぱふぅ家のホームページを検索・表示</h2>
0009: <h3><?= date("Y年n月j日G時\n") ?></h3>
引き数に与えられたアルファベットに現在日時が対応する。たとえば、nは月の数字(ゼロを付けない)、jは日の数字(ゼロを付けない)、Gは24時制の時の数字(ゼロを付けない)である。この他、さまざまな表示書式があるので、 関数 date をご覧いただきたい。ここで関数dateはHTMLの中に組み込まれている。

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

変数 $InputFile は、ぱふぅ家のホームページをキーワード検索するページのURLである。検索キー "PHP" を指定して、変数に代入しておく。

変数 $Pattern は、ぱふぅ家のホームページの検索結果から抽出する部分を検索するための正規検索パターンである。詳細は後で述べる。
解説:文字コードの扱い
0022: //内部エンコーディング
0023: mb_internal_encoding('UTF-8'); //Google newsのエンコーディングはUTF-8
文字コードの詳しい話は「文字コードの話」をご覧いただきたい。

PHPでテキストファイルを扱う場合、まず、そのファイルの文字コードに注意する。
ぱふぅ家のホームページは UTF-8 で記述されているので、 プログラムの冒頭で関数 mb_internal_encoding を使い、内部処理で UTF-8 を使うことを宣言する。もし文字コードがEUCなら"EUC"と、UTF-8なら"UTF-8"と記述すればよい。
PHPのマニュアルによると、シフトJISでの動作は保証していないとあるが、この程度のプログラムでは問題なく動作するようだ。(より複雑なプログラムでは、すべてのテキストをEUC-JPに変換する必要があるかもしれない)
解説:ファイルのオープン
0042: //ファイル・オープン
0043: if (isphp5over()) {
0044: //PHP5以上では証明書の検証を無効化
0045: $ctx = stream_context_create(array('ssl' => array('verify_peer' => FALSE)));
0046: $fp = fopen($InputFile, 'r', FALSE, $ctx);
0047: } else {
0048: $fp = fopen($InputFile, 'r');
0049: }
ちなみに、PCのローカルディスクにあるファイルをオープンする場合も関数 fopen を使う。
なお、当サイトが稼働しているサーバの都合上、証明書の検証を無効化している。

正常にファイルがオープンできると、関数 fopen はリソース番号を返す。今後、このファイルへのアクセスはリソース番号を介して行うことになるので、リソース番号を変数 $fp に保存しておく。
関数 fopen はエラーを発生する場合がある。たとえば、引き数に指定されたファイルがない場合(HTTPサーバの404エラー)などだ。そこで、エラー対処も記述しておく。
関数 fopen は、エラー発生時に FALSE を返す。もし変数$fpがFALSEだったら、エラー表示を行い、関数 exit によってプログラムを強制終了する。
解説:ファイルを読んで記事見出しを抽出する
0055: //コンテンツを1行ずつ読み込んで処理する
0056: while (! feof($fp)) {
0057: $s = fgets($fp);
0058: $n = preg_match_all($Pattern, $s, $ar, PREG_SET_ORDER);
0059: //マッチングしたすべての箇所を表示する
0060: for ($i = 0; $i < $n; $i++) {
0061: echo '<li><a href="' . $ar[$i][1] . '" target="_blank">';
0062: echo $ar[$i][2] . "</a><br />\n";
0063: }
読み込んだ1行は、変数 $s に代入する。

このプログラムの目的は、ぱふぅ家のホームページの検索結果から記事見出しとハイパーリンクを抽出することである。
読み込んだ行には複数の見出しが含まれているが、各々は事前に設定した正規表現パターン $Pattern を有する。
そこで、読み込んだ行 $s に含まれるすべての見出しパターンを抽出するために、関数 preg_match_all を使う。
関数 preg_match_all は、引き数の正規表現パターンに合致するすべての部分文字列を配列に格納し、合致した部分文字列の数を返す。
合致した部分文字列とは、すなわち記事見出しである。そこで、逐次、部分文字列を表示させることでプログラムの目的を達する。この作業をテキストファイルの終わりまで繰り返す。
正規表現については、「PHPで正規表現」をあわせてご覧いただきたい。

関数 feof は、ファイルの終端まで来たら TRUE を、そうでなければ FALSE を返す。ここでは否定演算子 ! を付けて、ファイル終端に到達するまで while ループを回し、ファイルを読んで記事見出しを抽出・表示させる処理を続ける、という形になる。
ファイルを閉じる
0065: //ファイル・クローズ
0066: fclose($fp);
質疑応答
実際に「プログラムを実行する」をしたのですが、検索結果が0件で、Google newsよりと、システム日付、ロゴしか表示されません。
デバックしていくと、
$n = preg_match_all($Pattern, $s, $ar, PREG_SET_ORDER);
の部分で、結果が0件になっているようなのですが、それが原因でしょうか。正規表現にマッチするものがないのでしょうか。
お忙しいところお手数ですが、解決方法をご教授願えますでしょうか。
ちなみに環境としましては、PHP5、Apache2.2を使用しております。
【回答】
プログラムが古く、最近のGoogleNewsに対応していませんでした。
「サンプル・プログラムの解説」でも述べたように、正規表現パターンが変わっていたことと、GoogleNews自体の文字コードがシフトJISからUTF-8に変更されていました。
そこで、最新のGoogleNewsを読み込めるようにプログラムを修正したので、どうぞお試しください。
参考サイト
- PHPで正規表現:ぱふぅ家のホームページ
そこで今回は、ぱふぅ家のホームページの検索URLにアクセスし、タイトルとハイパーリンクを抽出して表示するプログラムを紹介する。
2004年(平成16年)11月に公開した最初のプログラムは、Googleニュースを読み込むものだったが、その後、Googleニュースのコンテンツ構造が複雑化してしまい、入門者向けに適したプログラムが作成できそうにないため、ぱふぅ家のホームページを読み込むプログラムに変更した。