即将用到爬虫,于是打算收集一下User Agent(UA)数据。接着马上想到自己网站的访问日志不就是现成的优质数据源吗?于是愉快的决定写个脚本统计一下Nginx访问日志中的UA信息。

这类简单操作,用脚本语言就足够,毫无疑问肯定要用最熟悉的PHP。打开vim就开撸,十几分钟下来,功能简单的统计脚本就搞定了。

脚本目前有三个功能:1. 找出所有的UA信息并排序; 2. 统计操作系统数据; 3. 统计浏览器数据。程序运行截图如下:

UA信息

操作系统信息

浏览器

用脚本统计最近一个月的访问日志,得到以下结果:

搜索引擎爬虫比较频繁,每天有好几千次数据访问;

Windows仍是份额最大的操作系统,Linux桌面依然份额很小;

Chrome目前是浏览器领域的霸主,其次是Firefox,Opera已经很小众了。

#!/usr/bin/php

<?php

/**

* @brief stat UA in access log

*

* @author tlanyan<tlanyan@hotmail.com>

* @link http://tlanyan.me

*/

/* vim: set ts=4; set sw=4; set ss=4; set expandtab; */

function getFileList(string $path) : array {

return glob(rtrim($path, "/") . "/*access.log*");

}

function statFiles(array $files) : array {

$stat = [];

echo PHP_EOL, "start to read files...", PHP_EOL;

foreach ($files as $file) {

echo "read file: $file ...", PHP_EOL;

$contents = getFileContent($file);

foreach ($contents as $line) {

$ua = getUA($line);

if (isset($stat[$ua])) {

$stat[$ua] += 1;

} else {

$stat[$ua] = 1;

}

}

}

echo "stat all files done!", PHP_EOL, PHP_EOL;

return $stat;

}

function getFileContent(string $file) : array {

if (substr($file, -3, 3) === ".gz") {

return gzfile($file);

}

return file($file);

}

function getUA(string $line) : ?string {

// important! Nginx log format determins the UA location in the line!

// You may have to refactor following codes to get the right result

// UA starts from fifth double quote

$count = 0; $offset = 0;

while ($count < 5) {

$pos = strpos($line, '"', $offset);

if ($pos === false) {

echo "Error! Unknown line: $line", PHP_EOL;

return null;

}

$count ++;

$offset = $pos + 1;

}

$end = strpos($line, '"', $offset);

return substr($line, $offset, $end - $offset);

}

function usage() {

echo "Usage: php statUA.php [option] [dir]", PHP_EOL;

echo " options:", PHP_EOL;

echo " -h: show this help", PHP_EOL;

echo " -v: verbose mode", PHP_EOL;

echo "-n NUM: UA list number", PHP_EOL;

echo " dir: directory to the log files", PHP_EOL;

echo PHP_EOL;

}

function filterUA(array& $stat, array $UAFilters) {

$filterCount = 0;

foreach ($UAFilters as $filter) {

foreach ($stat as $ua => $count) {

if (stripos($ua, $filter) !== false) {

$filterCount += $count;

unset($stat[$ua]);

}

}

}

echo "filter $filterCount records!", PHP_EOL;

}

function printCount(array $stat) {

$sum = array_sum($stat);

foreach ($stat as $key => $count) {

echo $key, " : ", $count, ", percent: ", sprintf("%.2f", 100*$count/$sum), PHP_EOL;

}

}

function statOS(array $UAs) : array {

global $debug;

echo PHP_EOL, "stat OS...", PHP_EOL;

$os = ["Windows", "MacOS", "Linux", "Android", "iOS", "other"];

$stat = array_fill_keys($os, 0);

foreach ($UAs as $key => $count) {

if (strpos($key, "Windows") !== false) {

$stat["Windows"] += $count;

} else if (strpos($key, "Macintosh") !== false) {

$stat["MacOS"] += $count;

// must deal Android first, then Linux

} else if (strpos($key, "Android") !== false) {

$stat["Android"] += $count;

} else if (strpos($key, "Linux") !== false) {

$stat["Linux"] += $count;

} else if (strpos($key, "iPhone") !== false || strpos($key, "iOS") !== false || strpos($key, "like Mac OS") !== false || strpos($key, "Darwin") !== false) {

$stat["iOS"] += $count;

} else {

if ($debug) {

echo "other: $key, count: $count", PHP_EOL;

}

$stat["other"] += $count;

}

}

return $stat;

}

function statBrowser(array $UAs) : array {

global $debug;

echo PHP_EOL, "stat brwoser...", PHP_EOL;

$browsers = ["Chrome", "Firefox", "IE", "Safari", "Edge", "Opera", "other"];

$stat = array_fill_keys($browsers, 0);

foreach ($UAs as $key => $count) {

if (strpos($key, "MSIE") !== false) {

$stat["IE"] += $count;

} else if (strpos($key, "Edge") !== false) {

$stat["Edge"] += $count;

} else if (strpos($key, "Firefox") !== false) {

$stat["Firefox"] += $count;

} else if (strpos($key, "OPR") !== false) {

$stat["Opera"] += $count;

// first Chrome, then Safari

} else if (strpos($key, "Chrome") !== false) {

$stat["Chrome"] += $count;

} else if (strpos($key, "Safari") !== false) {

$stat["Safari"] += $count;

} else {

if ($debug) {

echo "other: $key, count: $count", PHP_EOL;

}

$stat["other"] += $count;

}

}

return $stat;

}

function parseCmd() {

global $debug, $num, $path, $argc, $argv;

$optind = null;

$options = getopt("hvn:", [], $optind);

if ($argc > 2 && empty($options)) {

usage();

exit(1);

}

if (isset($options['h'])) {

usage();

exit(0);

}

if (isset($options['v'])) {

$debug = true;

}

if (isset($options['n'])) {

$num = intval($options['n']);

if ($num <= 0) {

$num = 10;

}

}

if ($argc === 2 && empty($options)) {

$path = $argv[1];

}

if ($argc > $optind) {

$path = $argv[$optind];

}

if (!is_dir($path)) {

echo "invalid directory: $path", PHP_EOL;

exit(1);

}

if ($debug) {

echo "num: $num", PHP_EOL;

echo "verbose: ", var_export($debug, true), PHP_EOL;

echo "path: $path", PHP_EOL;

}

}

if (version_compare(PHP_VERSION, "7.1") < 0) {

exit("scripts require PHP >=7.1");

}

$path = ".";

$debug = false;

$num = 10;

$UAFilters = [

"spider",

"bot",

"wget",

"curl",

];

parseCmd();

$files = getFileList($path);

if (empty($files)) {

echo '"' . realpath($path) . '" does not contain access log files.', PHP_EOL;

exit(0);

}

$allUA = statFiles($files);

if (empty($allUA)) {

echo "no data", PHP_EOL;

exit(0);

}

filterUA($allUA, $UAFilters);

// sort array with count

uasort($allUA, function ($a, $b) {

return $b - $a;

});

if ($debug) {

print_r($allUA);

}

echo PHP_EOL, "---- top $num UA ----", PHP_EOL;

printCount(array_slice($allUA, 0, $num));

echo "-------------------", PHP_EOL;

$os = statOS($allUA);

echo PHP_EOL, "os count:", PHP_EOL;

printCount($os);

$browser = statBrowser($allUA);

echo PHP_EOL, "browser count:", PHP_EOL;

printCount($browser);

php日志数据统计,PHP统计Nginx日志的User Agent数据相关推荐

  1. linux nginx 日志查看,查看nginx日志_Linux系统怎么分析Nginx日志

    摘要 腾兴网为您分享:Linux系统怎么分析Nginx日志,追书神器,有信,虚拟机,天气预报等软件知识,以及云软件,东方财富股票软件,扑飞,名片扫描王,微信加人软件安卓,微主题,每日金股,电脑硬盘检测 ...

  2. ip访问次数统计 nginx_Linux分析Nginx日志统计IP访问次数的shell脚本

    平时运维遇到最多的就是nginx的日志分析了,要时常做系统监控,检查IP的访问次数是否有异常,防止恶意访问. 假设我的nginx日志如下: ....... 211.253.43.23 - - [03/ ...

  3. nginx 获取body参数_日志分析系列(外传二):Nginx日志统一化

    本系列故事纯属虚构,如有雷同实属巧合 为了完成对Nginx服务器的日志分析,小B对Q公司的Nginx日志做了统一化要求.下面是小B在统一化过程中遇到的一些知识点: Nginx日志与字段解析 Q公司的N ...

  4. python分析nginx日志_利用python分析nginx日志

    最近在学习python,写了个脚本分析nginx日志,练练手.写得比较粗糙,但基本功能可以实现. 脚本功能:查找出当天访问次数前十位的IP,并获取该IP来源,并将分析结果发送邮件到指定邮箱. 实现前两 ...

  5. 统计Apache或nginx日志里访问次数最多的前十个IP

    来源:http://www.07net01.com/2015/08/914079.html nginx awk '{print $1}' urlogfile | sort | uniq -c | so ...

  6. 【lnmp+ELK+Nginx+GeoIP】超详细新版ELK8.5.0解析收集Nginx日志并实现数据可视化与IP地址地图可视化教程-2022年11月版

    超详细新版ELK8.5.0+lnmp1.9解析收集Nginx日志并实现数据可视化与IP地址地图可视化教程-2022年11月版 前言 1.基础环境和所需要的软件包 1.1服务器配置(仅供参考) 1.2 ...

  7. 虎牙直播张波:掘金Nginx日志

    大家好!我是来自虎牙直播技术保障部的张波.今天主要会从数据挖掘层面跟大家探讨一下 Nginx 的价值.OpenResty 在虎牙的应用场景主要 WAF 和流控等方面,我今天主要分享的是" N ...

  8. Nginx 日志分析

    目录: 日志分析 日志的常用需求分析 Nginx 日志切割 日志分析 Nginx 默认日志路径/usr/local/nginx/logs/,其中包含访问日志 access.log 和错误 记 录 日 ...

  9. 运维配置:Nginx日志配置详解

    Nginx日志配置详解 前言 Nginx日志对于统计.系统服务排错很有用.Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志).通过访问日志我们可以得到用户的I ...

  10. php 监控nginx日志文件,Nginx 日志分析及实时监控

    本文档以 Nginx 日志为例,介绍如何使用日志分析服务来分析 Nginx 日志中的各种指标. 许多个人站长选取了 Nginx 作为服务器搭建网站,在对网站访问情况进行分析时,需要对 Nginx 访问 ...

最新文章

  1. python graph_python graph什么意思
  2. 算法导论 习题24.2-4 amp; 24.3-6 单源最短路径问题
  3. 如何用windbg查看_eprocess结构
  4. 带有无参数的存储过程
  5. b g opencv读入的图片 r_OpenCV提取显示一张图片(或者视频)的R,G,B颜色分量
  6. android 支付宝 40247,支付宝 app支付异常摘记 -- ALI40247
  7. 经验分享:三步走教你升级企业NAS设备
  8. 将你的blog变成英文版
  9. 【产品人卫朋】华为IPD流程体系:集成产品开发框架
  10. linux 安装 navicat
  11. 湛江景点旅游攻略!究竟有哪些你不容错过的景点?
  12. 葡萄城报表模板库更新!新增物流行业特色模板
  13. 图片上传File对象不兼容IE
  14. Day4----类训练(搬家具、烤地瓜)
  15. wordpress中文主题,开源wordpress中文免费主题模板
  16. 判断三维空间两线段是否相交(附代码)
  17. 超市小票案例--适合Java初级练习Scanner类以及Java基础语法的例题
  18. 有实力的APP开发公司应该具备哪些优势?
  19. Matlab:交换矩阵的两行(列)
  20. Android——Activity的生命周期

热门文章

  1. UI登陆页面素材|让设计师在竞争中脱颖而出
  2. 最火UI素材|短视频、直播APP套件,轻松搞定设计
  3. 服务器操作系统版本检查,服务器操作系统版本检查
  4. JS中配置打开邮箱的链接
  5. 在线教学视频的设计与实现
  6. Containerd 的前世今生和级入门教程
  7. 详解数据中心灾备切换技术
  8. 一个简单的fftw3例子:正弦信号的离散傅里叶变换
  9. leetcode题库:4.两个排序数组的中位数
  10. Java的native方法java.lang.UnsatisfiedLinkError