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]
ラグビーW杯 南アフリカ v 日本 世紀のジャイキリという衝撃
ラグビーW杯 南アフリカ v 日本、深夜世紀のジャイアントキリングに感涙。リアルタイムで観れたことに感謝(レスター岡崎に感謝(汗))。
これほど魂が震えたのは久しぶりです。個人的にはジョホールバルかWBC決勝か五輪女子ソフトか南アW杯デンマーク戦(現地)か、でも世界的には今日の勝利はそれ以上のインパクトです。RWC史上最大の衝撃ですから。どこに魂が震えたかというと試合展開も劇的でしたが、あの日本代表のメンタルの強さですね。TV画面からその気迫がひしひしと伝わってきました。そのメンタルに触れた観客もJAPANコールに。最後エンジンを組み、勝ちにこだわる選択にも感動しました。
やはり日本人は泥臭く粘り強くコツコツひたむきにやらないと世界では勝てないということですね。スモールベースボールにしろ、練習は嘘をつかない、まさしくそれでした。以前、エディー・ジョーンズ HCについて触れましたが、あの時の練習量も半端なかったですしね。
先日、プロフェッショナル・仕事の流儀というエディー・ジョーンズ ラグビー日本代表監督のNHK番組がありました。エディー監督いわく以下の点について説いてました。
- 強みを知り、強みを伸ばす
日本人の強み。それは、どんな過酷な練習にも耐え、向上心を持ち続ける”勤勉(タフ)さ”。真面目で忍耐力があること。それは間違いなく世界一です。他の国の選手なら、とっくに逃げ出しているでしょう。
(AM6~PM7までの過酷な練習って高校野球じゃないんだから。でも映像からは相当な過酷さが垣間見えました。)- ハッピーにしない
選手を成長させるために必要なのは、選手を正しく理解し、それに合った方法で“少しの不安”や“緊張感”を与えること。居心地がいいと能力は発揮できないからです。ときには少し突き放すことで、選手が100%安心しないようにしています。- どんどんミスさせる
日本の練習で一番間違っているのはミスをしないように練習すること。ノーミス、ノーミスと言うが、ミスするから上達する。失敗から学ぶということが重要。- 責任感を持たせる
各ポジションのリーダー(サブリーダー)が責任感を持つ必要がある。責任とは各ポジションのメンバーによいパフォーマンスをさせること。- 感情の波を小さく
指導者として、誰にでも感情に起伏があることを理解した上で、そうした波を最小限にとどめさせることが大切。引用元:SKYBLUES.ORG
アジアカップ2015 日本代表QF敗退 と アギーレ監督解任
南アフリカは白人:黒人の比率が1:8なんですよね(南アというといつもこの比率で見てしまう(汗))。5年前にサッカーW杯で現地に行きましたが、当時でもいまだ格差は凄まじいものがありました。南アにしてもオージーにしてもイギリス連邦加盟国ですからイギリスの影響を色濃く受けてます。同組にスコットランドがいるとはいえイギリス国内中、ジャイキリした日本をリスペクトしていて、その喜びようといったら日本人以上です。スポーツの力って凄いですね!ラグビー日本代表に「勇気」を貰いました。
最近涙腺が弱いのか(汗)、先ほど録画での再放送でもまた涙してしまいました。