サンプル・プログラム
解説:calendar
317: /**
318: * 検索結果一覧
319: * @param int $window ウィンドウID
320: * @return string なし
321: */
322: function putItems($window) {
323: global $Items;
324:
325: clear_error($window);
326: wb_delete_items(wb_get_control($window, IDC_RES_LISTVIEW));
327: $Items = array();
328:
329: $t = wb_get_value(wb_get_control($window, IDC_CALENDAR));
330: $month = date('m', $t) + 0;
331: $day = date('d', $t) + 0;
332:
333: $i = getDayToday($month, $day, $Items);
334: $i = getAnniversary($month, $day, $Items, $errmsg, $i);
335: usort($Items, 'sortItems');
336:
337: //表示
338: if ($i > 0) {
339: wb_create_items(wb_get_control($window, IDC_RES_LISTVIEW), $Items);
340: } else {
341: put_error($window, ERROR_NOTCONNECTED);
342: }
343: }
WinBinder関数 wb_get_value を呼び出すことで、現在選択されている年月日をUNIX TIMEで取り出すことができる。これを組み込み関数 date に通せば、月と日を取得できるという仕組みである。
解説:https通信対応
134: /**
135: * httpsサイトからコンテンツを受信
136: * @param string $url "https://" から始まるURL
137: * @param array $post POST変数を格納した連想配列("変数名"=>"値")
138: * @return string 取得したコンテンツ/FALSE 取得エラー
139: */
140: function file_get_contents_ssl($url, $post=NULL) {
141: $ch = curl_init($url);
142: curl_setopt($ch, CURLOPT_HEADER, FALSE);
143: curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
144: if ($post != NULL) {
145: curl_setopt($ch, CURLOPT_POST, TRUE);
146: curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
147: }
148: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //サーバ証明書検証をスキップ
149: curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 〃
150: $result = curl_exec($ch);
151: curl_close($ch);
152:
153: return $result;
154: }
php.ini の extension=php_curl を有効にする必要があるため、本プログラム線用の php.ini を "daytodaywin\" ディレクトリに配置し、コンパイル時に読み込むようにしてある。
第二引数 $post を指定したときは、POST渡しできるようにしている。これは、日本記念日協会にアクセスするときに使う。
解説:Wikipediaをスクレイピング
190: /**
191: * 今日は何の日 取得
192: * @param int $month, $day 月,日
193: * @param array $items 情報格納配列
194: * @param bool $lfn 脚注残す(省略時=FALSE)
195: * @return int 情報件数
196: */
197: function getDayToday($month, $day, &$items, $lfn=FALSE) {
198: $pat1 = "<span[\s\S]+id=\"できごと\">";
199: $pat2 = "<span[\s\S]+id=\"誕生日\">";
200: $pat3 = "<span[\s\S]+id=\"忌日\">";
201: $pat5 = "<li>[^\>]+([0-9]+年.+)<\/li>";
202: $pat6 = "([^0-9]*)([0-9]+)年(\s*[\((].[^\))]+[)\)].)?[ \-]+(.+)"; //年 - イベント
203: $pat7 = "([^0-9]*)([0-9]+)年[ \-]+(.+)?、([^(\(]+)*[^0-9]*([0-9]*)";
204: //年 - 名前、職業(生没年)
205: $pat8 = "<span[\s\S]+id=\"フィクションのできごと\">";
206:
207: //コンテンツ読み込み
208: $url = getURL_Wikipedia($month, $day);
209: $contents = file_get_contents_ssl($url);
210: if ($contents == FALSE) return FALSE;
211:
212: //解釈
213: $str = strtok($contents, "\n");
214: $mode = '';
215: $cnt = 0;
216: while ($str != FALSE) {
217: if (mb_eregi($pat1, $str) == 1) {
218: $mode = '出来事';
219: } else if (mb_eregi($pat8, $str) == 1) {
220: $mode = '架空';
221: } else if (mb_eregi($pat2, $str) == 1) {
222: $mode = '誕生';
223: } else if (mb_eregi($pat3, $str) == 1) {
224: $mode = '死亡';
225: } else if ($mode != '' && mb_eregi($pat5, $str, $arr) > 0) {
226: $str = strip_tags(trim($str));
227: if ($mode == '出来事' && mb_eregi($pat6, $str, $arr) > 1) {
228: $items[$cnt][0] = internal2sjis($mode);
229: $items[$cnt][1] = ($arr[1] == '') ? (int)$arr[2] : 0 - $arr[2];
230: $items[$cnt][2] = internal2sjis($lfn ? $arr[4] : eliminate_footnote($arr[4]));
231: $cnt++;
232: } else if (mb_eregi($pat7, $str, $arr) > 1) {
233: $items[$cnt][0] = internal2sjis($mode);
234: $items[$cnt][1] = ($arr[1] == '') ? (int)$arr[2] : 0 - $arr[2];
235: $items[$cnt][2] = internal2sjis($lfn ? $arr[3] : eliminate_footnote($arr[3]) . '(' . $arr[4]);
236: if ($arr[5] != '') {
237: if ($mode == '誕生') {
238: $items[$cnt][2] .= internal2sjis(';~' . $arr[5] . '年');
239: } else {
240: $items[$cnt][2] .= internal2sjis(';' . $arr[5] . '年~');
241: }
242: }
243: $items[$cnt][2] .= internal2sjis(')');
244: $cnt++;
245: }
246: }
247: $str = strtok("\n");
248: }
249:
250: return $cnt;
251: }
「PHPでテキストの読みやすさを調べる(Windowsアプリ版)」で紹介したとおり、preg 系関数に動作不具合があるようなので、すべて mb_erege 系関数で処理している。
検索結果は「PHPで Windows用国立国会図書館検索プログラムをつくる」で使った ListView である。
解説:日本記念日協会をスクレイピング
253: /**
254: * 日本記念日協会のページをスクレイピングして記念日を取り出す
255: * @param string $contents ページ内容
256: * @param array $items 記念日を格納する配列
257: * @param int $cnt 情報を追加する配列の最初の番号
258: * @return int 情報の総数
259: */
260: function scrapingAnniversary($contents, &$items, $cnt) {
261: $pat = '<a\s+class="winDetail"\s+href="([^"]+)"><font[^>]+>([^<]+)</font>';
262: $mode = '記念日';
263:
264: $tok = strtok($contents, "\n");
265: while ($tok != FALSE) {
266: if (mb_eregi($pat, $tok, $arr) > 0) {
267: $items[$cnt][0] = internal2sjis($mode);
268: $items[$cnt][1] = '';
269: $items[$cnt][2] = internal2sjis($arr[2]);
270: $cnt++;
271: }
272: $tok = strtok("\n");
273: }
274:
275: return $cnt;
276: }
278: /**
279: * 指定月日の記念日を取得する
280: * @param int $month, $day 月日
281: * @param array $items 記念日を格納する配列
282: * @param string $errmsg エラーメッセージ格納用
283: * @param int $cnt 情報を追加する配列の最初の番号
284: * @return int 情報の総数
285: */
286: function getAnniversary($month, $day, &$items, &$errmsg, $cnt) {
287: //パラメータをPOST渡しする
288: $url = KINENBI_URL;
289: $post = array(
290: 'MD' => $month,
291: 'M' => $month,
292: 'D' => $day
293: );
294: $errmsg = '';
295:
296: $res = file_get_contents_ssl($url, $post);
297: if ($res == FALSE) {
298: $errmsg = '日本記念日協会のサイトにアクセスできません.';
299: } else {
300: $cnt = scrapingAnniversary($res, $items, $cnt);
301: }
302:
303: return $cnt;
304: }
日本記念日協会から、指定した月日の記念日を取得する。
コンパイル
参考サイト
- PHPで今日は何の日か調べる:ぱふぅ家のホームページ
- PHPで記念日を表示する:ぱふぅ家のホームページ
- C++ で今日は何の日か調べる:ぱふぅ家のホームページ
(2021年1月31日)記念日も表示するようにした。