基本的に、コードの速度を向上させるためにできることは主に 3 つあります。
外部ページの負荷を別の時間にオフロードします(つまり、cron を使用します) 。
Linuxベースのサーバーでは、何を提案すればよいかはわかりますが、Windowsを使用していると、同等のものが何であるかわかりませんが、Linux用のCronを使用すると、特定のスケジュール時間オフセットでスクリプトを起動できます-バックグラウンドで-そうではありませんブラウザを使用します。基本的には、 (データを更新する必要がある頻度に応じて)特定の時間オフセットで Web サイトのページを取得し、それらの Web ページをローカル システム上のファイルに書き込むことだけを目的とするスクリプトを作成することをお勧めします。
$listOfSites = array(
'http://www.something.com/page.htm',
'http://www.something-else.co.uk/index.php',
);
$dirToContainSites = getcwd() . '/sites';
foreach ( $listOfSites as $site ) {
$content = file_get_contents( $site );
/// i've just simply converted the URL into a filename here, there are
/// better ways of handling this, but this at least keeps things simple.
/// the following just converts any non letter or non number into an
/// underscore... so, http___www_something_com_page_htm
$file_name = preg_replace('/[^a-z0-9]/i','_', $site);
file_put_contents( $dirToContainSites . '/' . $file_name, $content );
}
このスクリプトを作成したら、必要なだけ定期的に実行するようにサーバーを設定する必要があります。次に、統計を表示するフロントエンド スクリプトを変更して、ローカル ファイルから読み取ることができます。これにより、速度が大幅に向上します。
ディレクトリからファイルを読み取る方法については、次を参照してください。
http://uk.php.net/manual/en/function.dir.php
または、より簡単な方法(ただし、問題が発生する可能性があります)は、サイトの配列を再ステップし、上記の preg_replace を使用して URL をファイル名に変換し、フォルダー内のファイルの存在を確認することです。
統計の計算結果をキャッシュする
これは、かなり頻繁にアクセスしたい統計ページである可能性が非常に高いです(公開ページほど頻繁ではありませんが、それでも)。cron ベースのスクリプトが実行されるよりも頻繁に同じページにアクセスする場合、すべての計算を再度実行する理由はありません。基本的に、出力をキャッシュするために必要なことは、次のようなことを行うことだけです。
$cachedVersion = getcwd() . '/cached/stats.html';
/// check to see if there is a cached version of this page
if ( file_exists($cachedVersion) ) {
/// if so, load it and echo it to the browser
echo file_get_contents($cachedVersion);
}
else {
/// start output buffering so we can catch what we send to the browser
ob_start();
/// DO YOUR STATS CALCULATION HERE AND ECHO IT TO THE BROWSER LIKE NORMAL
/// end output buffering and grab the contents so we now have a string
/// of the page we've just generated
$content = ob_get_contents(); ob_end_clean();
/// write the content to the cached file for next time
file_put_contents($cachedVersion, $content);
echo $content;
}
キャッシュを開始したら、いつキャッシュを削除またはクリアする必要があるかを認識する必要があります。そうしないと、統計出力が変化しません。この状況に関しては、キャッシュをクリアするのに最適なタイミングは、外部 Web ページを再度取得する時点です。したがって、この行を「cron」スクリプトの最後に追加する必要があります。
$cachedVersion = getcwd() . '/cached/stats.html';
unlink( $cachedVersion ); /// will delete the file
キャッシュ システムには他にも速度を向上させることができます(外部 Web ページの変更時間を記録し、更新されたときにのみ読み込むこともできます)が、説明を簡単にするように努めました。
この状況では HTML パーサーを使用しないでください
HTML ファイルをスキャンして 1 つの特定の一意の値を取得する場合、本格的な HTML パーサーや軽量の HTML パーサーを使用する必要はありません。RegExp を誤って使用することは、多くのスタートアップ プログラマーが陥りがちなことの 1 つであり、常に尋ねられる質問です。これにより、より多くの経験豊富なコーダーからの多くの自動ひざまずく反応が、次のロジックに自動的に準拠するようになりました。
if ( $askedAboutUsingRegExpForHTML ) {
$automatically->orderTheSillyPersonToUse( $HTMLParser );
} else {
$soundAdvice = $think->about( $theSituation );
print $soundAdvice;
}
HTMLParsers は、マークアップ内のターゲットがそれほど一意でない場合、または一致するパターンが非常に脆弱なルールに依存しているため、余分なタグまたは文字が発生した瞬間に壊れる場合に使用する必要があります。速度を上げたい場合ではなく、コードの信頼性を高めるために使用する必要があります。すべての要素のツリーを構築しないパーサーでさえ、なんらかの形式の文字列検索または正規表現表記を使用するため、使用しているライブラリ コードが非常に最適化された方法でコンパイルされていない限り、適切にコーディングされたものには勝てません。 strpos/preg_match ロジック。
あなたが解析しようとしている HTML を見たことがないことを考えると、私はかなり外れている可能性がありますが、あなたのスニペットについて見たことから、strpos と preg_match の組み合わせを使用して値を見つけるのは非常に簡単なはずです。明らかに、HTML がより複雑で、ランダムに複数出現する可能性がある<dt>Win rate</dt><dd><div>50%</div></dd>
場合は問題が発生しますが、それでも HTMLParser には同じ問題が発生します。
$offset = 0;
/// loop through the occurances of 'Win rate'
while ( ($p = stripos ($html, 'win rate', $offset)) !== FALSE ) {
/// grab out a snippet of the surrounding HTML to speed up the RegExp
$snippet = substr($html, $p, $p + 50 );
/// I've extended your RegExp to try and account for 'white space' that could
/// occur around the elements. The following wont take in to account any random
/// attributes that may appear, so if you find some pages aren't working - echo
/// out the $snippet var using something like "echo '<xmp>'.$snippet.'</xmp>';"
/// and that should show you what is appearing that is breaking the RegExp.
if ( preg_match('#^win\s+rate\s*</dt>\s*<dd>\s*<div>\s*([0-9]+%)\s*<#i', $snippet, $regs) ) {
/// once you are here your % value will be in $regs[1];
break; /// exit the while loop as we have found our 'Win rate'
}
/// reset our offset for the next loop
$offset = $p;
}
知っておくべき落とし穴
上記のコメントで述べたように、PHP を初めて使用する場合、上記はかなり複雑に思えるかもしれません。あなたがやろうとしていることは、特に最適かつ高速に実行したい場合、非常に複雑です。ただし、私が提供したコードをすべて実行し、よくわからない/聞いたことのないビットを調査すると(php.net はあなたの友人です)、より良い方法を理解できるはずです。あなたがしていることを達成します。
ただし、先を推測すると、上記で直面する可能性のある問題のいくつかを次に示します。
ファイル権限エラー- ローカル オペレーティング システムとの間でファイルを読み書きできるようにするには、適切な権限が必要です。特定のディレクトリにファイルを書き込めない場合は、使用しているホストで書き込みが許可されていない可能性があります。このような場合は、フォルダへの書き込み権限を取得する方法について問い合わせることができます。それができない場合は、代わりにデータベースを使用するように上記のコードを簡単に変更できます。
コンテンツが表示されません。出力バッファリングを使用すると、echo コマンドと print コマンドがすべてブラウザに送信されず、代わりにメモリに保存されます。スクリプトが終了すると、PHP は保存されているすべてのコンテンツを自動的に出力するはずですが、ob_end_clean() などのコマンドを使用すると、実際には「バッファ」が消去されるため、すべてのコンテンツが消去されます。これは、何かをエコーしていることがわかっているときに混乱を招く状況につながる可能性があります..しかし、それは表示されません。
(ミニ免責事項 :) 上記のすべてを手動で入力したので、PHP エラーがあることに気付くかもしれません。もしそうなら、それらは不可解です。ここに書き戻してください。StackOverflow が役に立ちます)