侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

利用PHP如何统计Nginx日志的User Agent数据

php  /  管理员 发布于 7年前   200

前言

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

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

脚本目前有三个功能:

1. 找出所有的UA信息并排序; 2. 统计操作系统数据; 3. 统计浏览器数据。

程序运行截图如下:

1、UA信息

2、操作系统信息

3、浏览器

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

  • 搜索引擎爬虫比较频繁,每天有好几千次数据访问;
  • Windows仍是份额最大的操作系统,Linux桌面依然份额很小;
  • Chrome目前是浏览器领域的霸主,其次是Firefox,Opera已经很小众了。

最后附上PHP脚本的代码,也可以从本人的Github里找到:https://github.com/tlanyan/Scripts/blob/master/statUA.php

#!/usr/bin/php * @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 countuasort($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);

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对AIDI的支持。

您可能感兴趣的文章:

  • 详解php+nginx 服务发生500 502错误排查思路
  • 深入分析nginx+php-fpm服务HTTP状态码502
  • 详解nginx+php执行请求的工作原理
  • php和nginx交互实例讲解


  • 上一条:
    PHP获取ttf格式文件字体名的方法示例
    下一条:
    浅谈php://filter的妙用
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客