PHPで記念日を表示する

(1/1)
一般社団法人 日本記念日協会は企業、団体、個人などによってすでに制定されている記念日、 新しく制定をした記念日についての認定と登録を行っており、登録された記念日が検索できるようになっている。そこで今回は、PHPを使って日本記念日協会のトップページをスクレイピングし、指定した月日の記念日を表示するプログラムを作ってみることにする。

(2022年2月23日)ツイート機能追加

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

PHPで記念日を表示する

目次

サンプル・プログラムのダウンロード

圧縮ファイルの内容
anniversary.phpサンプル・プログラム本体

解説:初期値など

初期値などは、あらかじめ定数で定義しておく。
変更不可となっている定数以外は、自由に変更できる。

記念日一覧をツイートする機能については、「PHPでTwitterに画像付きメッセージ投稿」を参考にしていただきたい。

  10: // 初期化処理 ================================================================
  11: define('INTERNAL_ENCODING', 'UTF-8');
  12: mb_internal_encoding(INTERNAL_ENCODING);
  13: mb_regex_encoding(INTERNAL_ENCODING);
  14: define('MYSELF', basename($_SERVER['SCRIPT_NAME']));
  15: define('REFERENCE', 'https://www.pahoo.org/e-soul/webtech/php05/php05-21-01.shtm');
  16: 
  17: //プログラム・タイトル
  18: define('TITLE', '記念日を表示する');
  19: 
  20: //リファラチェック+リリースフラグの設定
  21: if (isset($_SERVER['HTTP_HOST']) && ($_SERVER['HTTP_HOST'] == 'localhost')) {
  22:     define('FLAG_RELEASE', FALSE);
  23:     define('REFER_ON', '');
  24:     ini_set('display_errors', 1);
  25:     ini_set('error_reporting', E_ALL);
  26: else {
  27:     //リリース・フラグ(公開時にはTRUEにすること)
  28:     define('FLAG_RELEASE', TRUE);
  29:     //リファラ・チェック(直リン防止用;空文字ならチェックしない)
  30:     define('REFER_ON', 'www.pahoo.org');
  31: }
  32: 
  33: //ツイート・ボタン  TRUE:有効,FALSE:無効
  34: //参考 https://www.pahoo.org/e-soul/webtech/php06/php06-57-01.shtm
  35: define('TWITTER', FALSE);
  36: 
  37: //Twitterクラス:include_pathが通ったディレクトリに配置
  38: if (TWITTER) {
  39:     require_once('pahooTwitterAPI.php');
  40: }
  41: 
  42: //画像化したいオブジェクト
  43: define('TARGET', 'target');
  44: 
  45: //表示幅(ピクセル)
  46: define('WIDTH', 550);
  47: 
  48: //リクエストURL(日本記念日協会)(※変更不可)
  49: define('KINENBI_URL', 'https://www.kinenbi.gr.jp/');

解説:指定月日の記念日を取得する

ユーザー関数 getAnniversary は、指定月日の記念日を取得する。
変数 MDM に月を、変数 D に日を指定し、日本記念日協会のトップページにPOST渡しすることで、その月日の記念日を表示する。この処理を、後述するユーザー関数 getContentsWithPOST に実行させ、受け取ったコンテンツ(HTML文)を scrapingAnniversary によってスクレイピングし、記念日を配列 $items に格納する。

 297: /**
 298:  * 指定月日の記念日を取得する
 299:  * @param   int $month, $day 月日
 300:  * @param   array $items   記念日を格納する配列
 301:  * @param   string $errmsg エラーメッセージ格納用
 302:  * @return  int 記念日の数
 303: */
 304: function getAnniversary($month, $day, &$items, &$errmsg) {
 305:     //パラメータをPOST渡しする
 306:     $url = KINENBI_URL;
 307:     $post = array(
 308:         'MD' => $month,
 309:         'M'  => $month,
 310:         'D'  => $day
 311:     );
 312:     $errmsg = '';
 313: 
 314:     $res = getContentsWithPOST($url, $post);
 315:     if ($res == FALSE) {
 316:         $errmsg = '日本記念日協会のサイトにアクセスできません.';
 317:     } else {
 318:         $cnt = scrapingAnniversary($res, $items);
 319:     }
 320: 
 321:     return $cnt;
 322: }

解説:パラメータをPOST渡しコンテンツを取得

ユーザー関数 getContentsWithPOST は、渡されたパラメータを指定URLにPOST渡しする。サイトへのアクセスに cURL関数を用いる。

 244: /**
 245:  * パラメータをPOST渡しコンテンツを取得
 246:  * @param   string $url リクエストURL
 247:  * @param   array  $data POST変数を格納した連想配列("変数名"=>"値") 
 248:  * @return  string 取得したコンテンツ/FALSE 取得エラー
 249: */
 250: function getContentsWithPOST($url, $data) {
 251:     //cURL送信
 252:     $curl = curl_init();
 253:     curl_setopt($curl, CURLOPT_URL , $url);
 254:     curl_setopt($curl, CURLOPT_HEADER, 1) ; 
 255:     curl_setopt($curl, CURLOPT_POST, TRUE);
 256:     curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);   //結果を文字列で
 257:     curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
 258:     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
 259:     curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
 260:     curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
 261:     curl_setopt($curl, CURLOPT_TIMEOUT, 5);
 262:     $res1 = @curl_exec($curl);
 263:     $res2 = @curl_getinfo($curl);
 264:     curl_close($curl);
 265: 
 266:     //結果処理
 267:     if ($res1 !FALSE) {
 268:         $res = substr($res1, $res2['header_size']);
 269:     } else {
 270:         $res = FALSE;
 271:     }
 272: 
 273:     return $res;
 274: }

解説:記念日を取り出す

ユーザー関数 scrapingAnniversary は、渡されたコンテンツ(HTML文)をスクレイピングし、記念日を配列 $items に格納する。

 276: /**
 277:  * 日本記念日協会のページをスクレイピングして記念日を取り出す
 278:  * @param   string $contents ページ内容
 279:  * @param   array  $items 記念日を格納する配列
 280:  * @return  int 記念日の数
 281: */
 282: function scrapingAnniversary($contents, &$items) {
 283:     $pat = '/<a\s+class\=\"winDetail\"\s+href\=\"([^\"]+)\"\>\<font[^>]+>([^<]+)<\/font>/ui';
 284: 
 285:     $cnt = 0;
 286:     if (preg_match_all($pat, $contents, $arr, PREG_SET_ORDER> 0) {
 287:         foreach ($arr as $data) {
 288:             $items[$cnt]['url'] = KINENBI_URL . $data[1];
 289:             $items[$cnt]['title'] = $data[2];
 290:             $cnt++;
 291:         }
 292:     }
 293: 
 294:     return $cnt;
 295: }

参考サイト

(この項おわり)
header