WordPress のアクセス解析には現在 Counterize II と Google Analytics を併用しています。一時は Google Analytics へ一本化しようか迷ったのですが、いかんせんIPアドレスなどがデフォルトでは取得できませんので、不正アクセスやスパムなどでの BAN (拒否)ができません。これでは一本化はまず無理ですし、結局、併用がベターという結論に至りました。いざという時に(生)ログが手元にあるという安心感もありますしね。
ただ、 CounterizeII のアクセス解析はデザインが旧態依然ですし、すでに4年以上更新がないため、そろそろアクセス解析プラグインの乗り換えを考えることにしました。いろいろなプラグインがある中で、見た目とテーブルの簡素さから StatPress 系の NewStatPress にすることにしました。
ただ、そのまま使い始めますとアクセスカウンターがまたゼロからのスタートになってしまいます。これ、なんとかしたいなーということで、CounterizeII のアクセスログを NewStatPress へマイグレーション(移行)することにしました。テーブル間でSQL一発のマイグレーションも可能ですが、やはりできるだけ資産(データ)を生かしてマイグレーションしたいなーと。
テーブル構成(ER図)
ER図
このER図は、A5:SQL Mk-2 というツールで作成したのですが、いままで使用した数々のER関連ツールの中でも、抜群ではないかと。今までのツールって帯に短し襷に長し的なところがあったんですよね。この分野では海外モノが多いツールの中で日本製ですし、とにかく使いやすく表示形式(物理、論理、データ型)のバリエーションやDDLへの落とし込み、はたまたDB接続にSSHトンネルがデフォルトで可能など、このツールの開発者はかゆいところに手が届くというか、ER図とはなんなのかをよく知ってますね。こんな優れ物ツールが無料ってある意味凄すぎです。上記ER図もリバースエンジニアリングから、ものの5分程度で作成できました。MS-Visio ならおそらく1時間はかかっていたかなーと。Donate を募ってらっしゃるので本当はしたいのですが、まずはここでの紹介からとさせてくださいね(汗)
SQLによるマイグレーション
フィールドマッピング
テーブルのフィールドマッピングは以下の通りです。テーブル名の接頭辞($wpdb->prefix)は、省略しています。
Counterize II | SQL | NewStatPress |
---|---|---|
Counterize.timstamp | ⇒ | statpress.date |
Counterize.timstamp | ⇒ | statpress.time |
Counterize_Pages.IP | ⇒ | statpress.ip |
Counterize_Pages.url | ⇒ | statpress.urlrequested |
Counterize_UserAgents.name | ⇒ | statpress.agent |
Counterize_Referers.name | ⇒ | statpress.referrer |
Counterize.timstamp | ⇒ | statpress.timestamp |
SQL
INSERT INTO statpress ( date, time, ip, urlrequested, agent, reverrer, timestamp) SELECT DATE_FORMAT(a.timestamp, '%Y%m%d') as date, DATE_FORMAT(a.timestamp, '%H:%i:%s') as time, a.IP, b.url, c.name as agent, d.name as referrer, a.timestamp FROM Counterize a LEFT JOIN Counterize_Pages b ON a.pageID = b.pageID LEFT JOIN Counterize_UserAgents c ON a.agentID = c.agentID LEFT JOIN Counterize_Referers d ON a.refererID = d.refererID ORDER BY id ASC ;
なお、CounterizeII のIPアドレスはデフォルトでは暗号化されています、私は CounterizeII をカスタマイズして暗号化せず生IPをロギングするよう変更していましたのでそのまま移行できますが、暗号化されたハッシュ値のままであれば、あまり使い道がなさそうなので移行不要かもしれませんね。
NewStatPress のログ解析処理を適用しマイグレーション
フィールドマッピング
Counterize II | SQL | NewStatPress | ||
---|---|---|---|---|
PHP | ||||
Counterize.timstamp | ⇒ | statpress.date | ||
Counterize.timstamp | ⇒ | statpress.time | ||
Counterize_Pages.IP | ⇒ | statpress.ip | ⇒ | statpress.nation |
Counterize_Pages.url | ⇒ | statpress.urlrequested | ⇒ | statpress.feed |
Counterize_UserAgents.name | ⇒ | statpress.agent | ⇒ | statpress.os statpress.browser statpress.spider |
Counterize_Referers.name | ⇒ | statpress.referrer | ⇒ | statpress.search statpress.searchengine |
Counterize.timstamp | ⇒ | statpress.timestamp |
PHPコード
#!/usr/bin/php <?php //require the WP bootstrap require_once('<WordPress Dir>/wp-load.php'); // Execute migration mig_StatAppend(); /** * CounterizeII to NewStatPress migration * */ function mig_StatAppend() { global $wpdb; $table_name = nsp_TABLENAME; $offset = $wpdb->get_row("SELECT count(*) as count FROM " . $table_name); $count = $offset->count; $start = $wpdb->get_row("SELECT id FROM " . counterize_logTable() . " ORDER BY id ASC LIMIT 1 OFFSET " . $count); $sql = "SELECT a.id, DATE_FORMAT(a.timestamp, '%Y%m%d') as date, DATE_FORMAT(a.timestamp, '%H:%i:%s') as time, ip, url, c.name as agent, d.name as referrer, a.timestamp FROM " . counterize_logTable() . " a LEFT JOIN " . counterize_pageTable() . " b ON a.pageID = b.pageID LEFT JOIN " . counterize_agentsTable() . " c ON a.agentID = c.agentID LEFT JOIN " . counterize_refererTable() . " d ON a.refererID = d.refererID WHERE id >= " . $start->id . " ORDER BY id ASC;"; $res = mysql_query($sql); while ($row = mysql_fetch_assoc($res)) { $id = $row['id']; $vdate = $row['date']; $vtime = $row['time']; $ipAddress = $row['ip']; $urlRequested = $row['url']; $userAgent = $row['agent']; $referrer = $row['referrer']; $timestamp = $row['timestamp']; $login = null; $urlRequested = mig_URL($urlRequested); $urlRequested = esc_sql($urlRequested); $referrer = esc_sql($referrer); $referrer = esc_html($referrer); $userAgent = esc_sql($userAgent); $userAgent = esc_html($userAgent); $os = nsp_GetOs($userAgent); $browser = nsp_GetBrowser($userAgent); $spider = nsp_GetSpider($userAgent); $searchengine = ''; $search_phrase = ''; if ($spider != '') { $os = ''; $browser = ''; } else { // Trap feeds $feed = nsp_IsFeed($urlRequested); // Get OS and browser $os = nsp_GetOs($userAgent); $browser = nsp_GetBrowser($userAgent); $exp_referrer = mig_GetSE($referrer); if ( isset($exp_referrer) ) { list($searchengine,$search_phrase) = explode("|",$exp_referrer); } } // Country (ip2nation table) or language $countrylang = ""; if ( $wpdb->get_var("SHOW TABLES LIKE 'ip2nation'") == 'ip2nation' ) { $sql2 = 'SELECT * FROM ip2nation WHERE ip < INET_ATON("'.$ipAddress.'") ORDER BY ip DESC LIMIT 0,1'; $qry = $wpdb->get_row($sql2); if ( $qry != null ) { $countrylang = $qry->country; } } $insert = "INSERT INTO " . $table_name . "( date, time, ip, urlrequested, agent, referrer, search, nation, os, browser, searchengine, spider, feed, user, timestamp ) VALUES ( '$vdate', '$vtime', '$ipAddress', '$urlRequested', '".addslashes(strip_tags($userAgent))."', '$referrer','" . addslashes(strip_tags($search_phrase))."', '".$countrylang."', '$os', '$browser', '$searchengine', '$spider', '$feed', '$login', '$timestamp' )"; $results = mysql_query( $insert ); if ($results < 1) { print "insert error: line $id\n"; } if ( ++$count % 1000 == 0 ) { print "$count\n"; } } } /** * Processing the url * * @param urlRequested the source url * @return processing the url */ function mig_URL($urlRequested = '') { if(substr($urlRequested,0,2) == '/?') { $urlRequested = substr($urlRequested,2); } if($urlRequested == '/') { $urlRequested = ''; } return $urlRequested; } /** * Get the search engines * * @param referrer the url to test * @return the search engine present in the url */ function mig_GetSE($referrer = null){ global $newstatpress_dir; $key = null; $lines = file($newstatpress_dir.'/def/searchengines.dat'); foreach($lines as $line_num => $se) { list($nome,$url,$key) = explode("|",$se); if(strpos($referrer,$url) === FALSE) continue; # find if $variables = nsp_GetQueryPairs(html_entity_decode($referrer)); $i = count($variables); while($i--){ $tab = explode("=",$variables[$i]); if($tab[0] == $key && count($tab) >= 2){return ($nome."|".urldecode($tab[1]));} } } return null; } ?>
マイグレーションの実行
NewStatPress プラグインのインストール
閉塞後 NewStatPress プラグインをインストールします。有効化したらダッシュボードの NewStatPress メニューの Tools > Database Tools から ip2nation もインストールしておきます。
ロギングの停止
次にロギングの停止ですが、NewStatPress メニューの Options > Filters > Parameters to ignore > IP addresses 欄に以下のようにCIDRで記載しますとロギングが停止します。本来ならIPアドレスを ANY で拒否すればよいので、 0.0.0.0/0 でよいはずなのですが、どうもサブネットマスクを /0 にするとempty($mask) 判定でひっかかり強制的 32 に変更されてしまい、正常に全IPアドレスのアクセス拒否ができません。そのためサブネットマスクを 1 にしアドレスを2つに分けました。
[/cc]
上記を追加すればロギングは停止しますので、メンテナンスモードを解除しサイトを開放します。なおログが新旧混ざってもよいのであればこの手順は不要です。
解析定義データの追加
ただし追加する際は、次の点にご注意ください。dat ファイルは上から順にマッチ検索しますので、数字が大きいほうを先に記述してください。FireFox40 と FireFox4 の場合は、FireFox40 を先に(上に)記述してください。例えばブラウザのバージョンが FireFox40 であった場合、FireFox4 が先に記述されていると FireFox4 にヒットしてしまい、バージョンは 40 であるのにも関わらず、4と判定されてしまいます。またブラウザのバージョンなどは未来のバージョンを記述しておいても特に問題ありません。
また spider.dat は、定義に該当しないアクセスは、すべて Visitor と判定され bot にも関わらず、アクセス数扱いにされてしまいますのでご注意ください。このファイルは、適宜メンテしないと正しいアクセス数が得られないのではないかと思います。ここは少々面倒ですね。
- browser.dat
Chrome 46|Chrome/46| Chrome 47|Chrome/47| Chrome 48|Chrome/48| Chrome 49|Chrome/49| Chrome 50|Chrome/50| Chrome 5|Chrome/5| Firefox 50|Firefox/50| Firefox 51|Firefox/51| Firefox 52|Firefox/52| Firefox 53|Firefox/53| Firefox 54|Firefox/54| Firefox 55|Firefox/55| Firefox 56|Firefox/56| Firefox 57|Firefox/57| Firefox 58|Firefox/58| Firefox 59|Firefox/59| Firefox 60|Firefox/60| Firefox 4|Firefox/4| Firefox 5|Firefox/5| Firefox 6|Firefox/6| Microsoft Edge|Edge/12| Microsoft Edge|Edge/13| Microsoft Edge|Edge/14| Microsoft Edge|Edge/15|
- os.dat
Windows 10|WindowsNT10.0|
- searchengine.dat
Yahoo は search.yahoo.com になっていますので、必ず search.yahoo. に変更してください。
Yahoo|search.yahoo.|p| Bing|www.bing.com|q| ezweb|ezsch.ezweb.ne.jp|query| docomo|search.smt.docomo.ne.jp|MT| au|sp-search.auone.jp|q| Rakuten|websearch.rakuten.co.jp|qt| OCN|wsearch.ocn.ne.jp|MT| J:COM|search.myjcom.jp|q| So-net|www.so-net.ne.jp|query| JWord|search.jword.jp|name| Sleipnir|search.fenrir-inc.com|q| Lunascape|s.luna.tv|q| FMWORLD|search.azby.fmworld.net|q| MyVAIO|search.start.sony.jp|MT|
- spider.dat
360Spider|360Spider| Linkdex|linkdexbot| SimilarTech|SMTBot|
コンソール実行
また Web からでも実行は可能ですが、WordPress ディレクトリ配下ではなく外部の php ファイルが動作するディレクトリに配置する必要があります。HTML 表示になりますので改行の<br>を適宜入れておくとよいと思います。ただ Web からですとログ量にもよりますが、おそらくHTTP コネクションのタイムアウトになってしまう気がします。
1000
2000
3000
….
[/cc]
まず statpress テーブルに登録され件数を取得します。Counterize テーブルからこの件数に該当する位置の行を OFFSET 句で取得し、その行の id を取得します。この id が継続開始位置ですね。本当は副問い合わせを使って SQL 一発で id を取得したかったのですが、MySQL は LIMIT/OFFSET 句の副問い合わせはエラーになり、結局それぞれでSQLを投げて取得する方法になりました。イマイチ。PostgreSQL なら可能だと思いますね。
$offset = $wpdb->get_row("SELECT count(*) as count FROM " . $table_name); $count = $offset->count; $start = $wpdb->get_row("SELECT id FROM " . counterize_logTable() . " ORDER BY id ASC LIMIT 1 OFFSET " . $count);
WHERE id >= " . $start->id . "
[/cc]
差分の同期
終了したら、ロギングを再開するため先ほど NewStatPress メニューの Options > Filters > Parameters to ignore > IP addresses 欄の「0.0.0.0/1,128.0.0.0/1」を消去し保存します。最後にメンテナンスモードを解除し、マイグレーションは完了です。
最後に
ただCounterizeII ではスパイダー数が全く解らなかったのですが、NewStatPress にしてページビューより多くこんなに多いのかと少々驚きでした。 bot アクセスが多過ぎですね。
Firefox 40|Firefox/40|
↓
ブラウザ名|ユーザーエージェント|アイコンファイル名|
Firefox 40|Firefox/40|firefox|
[/cc]