php-tool-box:user-agent-pot
PHPでサイトに来たUser-Agentを片っ端から集めて一覧表示 - User-Agent POT
User-Agentを集計するPHPを作ってみた。
基本的にPHP1ファイルとMySQLのテーブル1つで動くが、tablesort.jsを組み込むと一覧表のソートが簡単にできて便利。
また、オプションとしてPEAR::Net_UserAgent_DetectとPEAR::Net_UserAgent_MobileによるUser-Agentの判別も組み込めるようにしたが、こちらは便利かどうかは微妙。無いほうが見た目がすっきりするかも。
あと、User-Agentに全角文字が入っている場合はDBに登録できないかも。
User-Agentのシェアを調べるというよりは、レアなUser-Agentを見つけるという用途に向いている。
サンプル
ソースコード
<?php /** * User-Agent POT * @version 0.1.0 * @see http://0-oo.net/sbox/php-tool-box/user-agent-pot * @copyright 2009 dgbadmin@gmail.com * @license http://0-oo.net/pryn/MIT_license.txt (The MIT license) * * 必要なもの * PHP * MySQL * PDO_MySQL * あると便利?なもの * tablesort.js * PEAR::Net_UserAgent_Detect * PEAR::Net_UserAgent_Mobile * * 補足 * カウントアップせずに表示したい場合はGETで readonly=1 を渡す * /* *【 STEP 1 】下記のSQLを実行し、MySQLにテーブルを作る * CREATE TABLE uapot_agents ( user_agent VARCHAR(200) NOT NULL, browser TEXT NULL, os TEXT NULL, mobile TEXT NULL, cnt INT(10) UNSIGNED NOT NULL DEFAULT 1, created_at DATETIME NOT NULL, updated_at DATETIME DEFAULT NULL, PRIMARY KEY (user_agent) ); /* * 【 STEP 2 】下記のDB接続の設定を自分の環境に合わせて書き換える * @see http://jp2.php.net/manual/ja/pdo.construct.php * @see http://jp2.php.net/manual/ja/ref.pdo-mysql.connection.php */ $dsn ='mysql:dbname=test'; $user = 'mysqluser'; //DB接続ユーザー $pass = 'mysqlpassword'; //DB接続パスワード $table = 'uapot_agents'; //テーブル名 /* * 【 STEP 3 】(Optional) 表の並び替え * ※別途、tablesort.jsが必要 * @see http://neil.fraser.name/software/tablesort/ */ $tableSortPath = 'tablesort.js'; //不要ならコメントアウトする /* * 【 STEP 4 】(Optional) ブラウザとOSの種類ごとの集計 * ※別途、PEAR::Net_UserAgent_Detectのインストールが必要 * @see http://pear.php.net/package/Net_UserAgent_Detect */ require('Net/UserAgent/Detect.php'); //不要ならコメントアウトする $detectFlg = class_exists('Net_UserAgent_Detect'); /* * 【 STEP 5 】(Optional) 携帯キャリアごとの集計 * ※別途、PEAR::Net_UserAgent_Mobileのインストールが必要 * @see http://pear.php.net/package/Net_UserAgent_Mobile */ require('Net/UserAgent/Mobile.php'); //不要ならコメントアウトする $mobileFlg = class_exists('Net_UserAgent_Mobile'); /* * 以降はUser-Agent POTにお任せを。 */ //DBの準備 $pdo = new PDO($dsn, $user, $pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); //登録データの作成 $params = array_fill(0, 7, null); if ($_SERVER['HTTP_USER_AGENT']) { $params[0] = $_SERVER['HTTP_USER_AGENT']; } else { $params[0] = ''; } if ($detectFlg) { //ブラウザ・OSの判別 $detecter = new Net_UserAgent_Detect($params[0]); $params[1] = $detecter->getBrowserString(); if ($params[1] == 'Unknown') { $params[1] = ''; } $params[2] = $detecter->getOSString(); if ($params[2] == 'Unknown') { $params[2] = ''; } $params[4] = $params[1]; $params[5] = $params[2]; } if ($mobileFlg) { //携帯キャリアの判別 $mobile = Net_UserAgent_Mobile::factory(); if ($mobile->isDoCoMo()) { $params[3] = 'DoCoMo'; } else if ($mobile->isEZweb()) { $params[3] = 'au'; } else if ($mobile->isSoftBank()) { $params[3] = 'SoftBank'; } else if ($mobile->isWillcom()) { $params[3] = 'Willcom'; } else if ($mobile->isNonMobile()) { $params[3] = ''; } else { $params[3] = 'Other Mobile'; } $params[6] = $params[3]; } //登録・更新 $sql = "INSERT INTO $table(user_agent, browser, os, mobile, created_at) \n"; $sql .= "VALUES(?, ?, ?, ?, NOW()) \n"; $sql .= " ON DUPLICATE KEY UPDATE \n"; $sql .= " cnt = cnt + 1, browser = ?, os = ?, mobile = ?, updated_at = NOW()"; if (!$_GET['readonly']) { $stmt = $pdo->prepare($sql); try { $stmt->execute($params); } catch (PDOException $e) { error_log('User-Agent 登録失敗 "' . $params[0] . '"'); } } //詳細取得 $detail = $pdo->query("SELECT * FROM $table ORDER BY cnt DESC, updated_at DESC"); //画面表示開始 ini_set('default_charset', 'utf8'); echo '<?xml version="1.0" encoding="UTF-8" ?>'; ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <title>User-Agent POT</title> <style type="text/css"> h1 { color: gray } table { margin-bottom: 2em; border-collapse: collapse } table.summary { float: left; margin-right: 3em } table.detail { clear: left } caption { font-weight: bold; text-align: left; white-space: nowrap } caption a { float: right } span.query { font-weight: normal; } th { background-color: silver; white-space: nowrap } table, th, td { border: solid 1px gray } th, td { padding: 3px } td.cnt { text-align: right } td.time { text-align: center; white-space: nowrap } </style> </head> <body> <h1>User-Agent POT</h1> <?php if ($detectFlg) { showSummary($pdo, $table, 'Browser'); showSummary($pdo, $table, 'OS'); } if ($mobileFlg) { showSummary($pdo, $table, 'Mobile'); } ?> <table class="detail" summary="User-Agent Detail"> <caption> <?php if ($_GET['time']) { echo '<a href="?readonly=1">Hide Times</a>'; } else { echo '<a href="?readonly=1&time=1">Show Times</a>'; } ?> User Agent Detail <span class="query"> ( Query <input type="text" onkeyup="query(this.value)" /> <span id="count"></span> ) </span> </caption> <thead> <tr> <th class="nocase">User-Agent</th> <?php if ($detectFlg) { echo '<th class="nocase">Browser</th><th class="nocase">OS</th>'; } if ($mobileFlg) { echo '<th class="nocase">Mobile</th>'; } echo '<th class="num">count</th>'; if ($_GET['time']) { echo '<th class="nocase time">first time</th><th class="nocase time">last time</th>'; } ?> </tr> </thead> <tbody id="detail"> <?php foreach ($detail as $row) { echo "<tr>\n"; echo '<td>' . htmlspecialchars($row['user_agent']) . "</td>\n"; if ($detectFlg) { echo '<td>' . htmlspecialchars($row['browser']) . "</td>\n"; echo '<td>' . htmlspecialchars($row['os']) . "</td>\n"; } if ($mobileFlg) { echo '<td>' . htmlspecialchars($row['mobile']) . "</td>\n"; } echo '<td class="cnt">' . $row['cnt'] . "</td>\n"; if ($_GET['time']) { echo '<td class="time">' . $row['created_at'] . "</td>\n"; echo '<td class="time">' . $row['updated_at'] . "</td>\n"; } echo "</tr>\n"; } ?> </tbody> </table> <div> powered by <a href="http://0-oo.net/sbox/php-tool-box/user-agent-pot">User-Agent POT</a> </div> <?php if ($tableSortPath) { echo '<script type="text/javascript" src="' . $tableSortPath . '"></script>'; } ?> <script type="text/javascript"> //<![CDATA[ var rows = document.getElementById("detail").getElementsByTagName("tr"); function query(text) { try { var regexp = new RegExp(text, "i"); } catch (e) { return; } var cnt = 0; for (var i = 0, len = rows.length; i < len; i++) { var row = rows[i]; if (text == "" || row.getElementsByTagName("td")[0].innerHTML.match(regexp)) { row.style.display = ""; cnt++; } else { row.style.display = "none"; } } document.getElementById("count").innerHTML = cnt; } //]]> </script> </body> </html> <?php function showSummary($pdo, $table, $type) { $column = strtolower($type); $sql = "SELECT $column, SUM(cnt) AS cnt FROM $table GROUP BY $column ORDER BY cnt DESC"; $summary = $pdo->query($sql); ?> <table class="summary" summary="<?php echo $type ?> Summary"> <caption><?php echo $type ?> Summary</caption> <thead> <tr> <th class="nocase"><?php echo $type ?></th><th class="num">count</th> </tr> </thead> <tbody> <?php foreach ($summary as $row) { ?> <tr> <td><?php echo htmlspecialchars($row[$column]) ?></td> <td class="cnt"><?php echo $row['cnt'] ?></td> </tr> <?php } ?> </tbody> </table> <?php }
php-tool-box/user-agent-pot.txt · 最終更新: 2009/02/15 00:01 by dgbadmin