ゼロと無限の間に

フリーでオープンソースなJavaScriptとかPHPとか。

ユーザ用ツール

サイト用ツール


サイドバー

何かありましたら、メールで連絡いただくか、ブログのどこかにコメント入れてくださいね ^_^

Menu

ゼロと無限の間に

はじめに

作った主なサイト

作った主な便利ツール(無料)

ログ (Blog)

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&amp;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