CakePHP5入門【コラム⑯】データ自動更新の改良
A子
たまに失敗してるみたいなんだよね(苦笑)
C菜
一日でも更新しない日があると、それ以降は自動更新できなくなっちゃいますよ~
(そういう更新アルゴリズムなので~)
A子
どうやら通信速度の関係で、JavaScriptによって動的に埋め込まれるデータを取得できないときがあるらしい
B美
スクレイピングの時に、たまたまアクセス過多になったとか…じゃないかな?
C菜
A子
|
1.privateメソッドである「waitForSelector」の改良
2.コマンドクラスの戻り値として「成功」「失敗」を返す 3.コマンド実行をシェルスクリプトで繰返し行う |
2番については、3番のための変更ね
(「失敗」時に再試行するため)
C菜
|
//Webページ内にJavaScriptによる値の埋め込みが完了するまで待つ(デフォルト値は最大30秒)
private function waitForSelector($page, string $selector, int $timeoutMs = 30000) { $start = microtime(true); while (true) { $exists = $page->evaluate( 'document.querySelectorAll("' . $selector . '").length' )->getReturnValue(); if ($exists > 0) { return; } if ((microtime(true) - $start) * 1000 > $timeoutMs) { throw new \RuntimeException("Timeout waiting for: $selector"); } usleep(500000); } } |
A子
|
//Webページ内にJavaScriptによる値の埋め込みが完了するまで待つ(デフォルト値は最大60秒)
private function waitForSelector($page, string $selector, int $timeoutMs = 60000) { $start = microtime(true); while (true) { $exists = $page->evaluate( "document.querySelector('$selector') !== null" )->getReturnValue(); if ($exists) { return true; } if ((microtime(true) - $start) * 1000 > $timeoutMs) { throw new \Exception("Selector timeout: $selector"); } usleep(200000); } } |
C菜
それって、ほとんど一緒じゃないですか~?
書き換える意味はあるのでしょうか~?
A子
「querySelectorAll」ではDOMの中を全件走査するから時間がかかるけど、「querySelector」では見つけた瞬間に終了するらしい
B美
JavaScriptによる埋め込みデータの分量が多い場合、「querySelectorAll」ではタイムアウト率が悪化する可能性があるってこと
C菜
それでは次、2番はどうなりますか~?
A子
あの中にエラーコードを返す記述を書くよ
|
//エラーが発生した場合、管理者あてにメール送信
if ($error_flag > 0) { $mailer = new Mailer('default'); $mailer->setFrom([FROM_ADDRESS => FROM_NAME]) ->setTo(TO_ADDRESS) ->setSubject(MAIL_SUBJECT) ->deliver(MAIL_BODY[$error_flag]); //スクレイピング関連のエラーの場合、エラーコードを返す if ($error_flag <= 5) { return static::CODE_ERROR; } } //正常終了 return static::CODE_SUCCESS; |
C菜
A子
そう教わったからそのまま書いただけ…
B美
(「class LotteryCommand extends Command」というクラス定義を見ても分かる通り、Commandクラスを「継承」してるから使えるってわけ)
具体的には「CODE_SUCCESS」は「0」で、「CODE_ERROR」は「1」ってだけなんだけどね
C菜
以前出てきた「self」を使って「self::CODE_ERROR」や「self::CODE_SUCCESS」ではダメなんでしょうか~?
B美
「self」でも良いし、それでもきちんと動くわよ
でも将来的に拡張される可能性があるフレームワークにおいては、「static」にするのがベストかな
(作法と言っても良い)
A子
どういうこと?
B美
つまり、継承先で書き換えられる可能性のある要素については「static」で指定しておくほうが、将来的な拡張性が高くなるってわけ
A子
(なんだか面倒くさくなってきた…)
よくわかんないけど、そういうもんだって思っておけばOK?
C菜
B美
まぁ、そこまで厳密に使い分ける必要もないんだけどね(苦笑)
A子
最後の3番だよ
見て分かるだろうけど、シェルスクリプトね
B美
「/home/bimi/html/numapp/bin/cake」の箇所は本番環境に合わせて変更するようにね
(特に「bimi」の箇所)
C菜
(最大試行回数は5回です~)
B美
それにしてもA子が自分で色々と動いたってのが驚きなんだけど…(苦笑)
A子
たまにはそういうこともあるよ
B美


