本文的作者是 Nikolay Koldunov,本文原文是
Apache log analysis with Pandas

注本文的图有问题,没法引用,还是去原文看下,这里作为一个引子。

%pylab inline

欢迎来到 pylab,一个基于 matplotlib 的 Python 环境【backend: module://IPython.kernel.zmq.pylab.backend_inline】。想要了解更多信息,请键入 'help(pylab)'。

在这个笔记中,我们将展示一个使用 pandas 分析 Apache 访问日志的简单示例。这是我第一次使用 pandas,并且我确定会有更好以及更有效率的方式来做这里展示的事情。所以评论,建议和修正我的蹩脚英语是非常欢迎的。你可以给我发送邮件或者是为这个笔记的 github 创建一个 PR。

加载和解析数据

我们将需要 apachelog 模块,用来解析日志。我们也需要知道设置在 Apache 配置中的日志格式。在我的案例中,我没有访问 Apache 配置,但是主机托管服务提供商在他的帮助页提供了日志格式的描述。下面是它自己的格式以及每个元素的简单描述:

format = r'%V %h  %l %u %t \"%r\" %>s %b \"%i\" \"%{User-Agent}i\" %T'

这里(大部分拷贝自这个 SO 文章):

%V          - 根据 UseCanonicalName 设置的服务器名字
%h          - 远程主机(客户端 IP)
%l          - identity of the user determined by identd (not usually used since not reliable)
%u          - 由 HTTP authentication 决定的 user name
%t          - 服务器完成处理这个请求的时间
%r          - 来自客户端的请求行。 ("GET / HTTP/1.0")
%>s         - 服务器端返回给客户端的状态码(200, 404 等等。)
%b          - 响应给客户端的响应报文大小 (in bytes)
\"%i\"      - Referer is the page that linked to this URL.
User-agent  - the browser identification string
%T          - Apache 请求时间
In [3]:import apachelog, sys

设置格式:

In [4]:fformat = r'%V %h %l %u %t \"%r\" %>s %b \"%i\" \"%{User-Agent}i\" %T'

创建一个解析器:

In [5]:p = apachelog.parser(fformat)

简单字符串:

koldunov.net 85.26.235.202 - - [16/Mar/2013:00:19:43 +0400] "GET /?p=364 HTTP/1.0" 200 65237 "http://koldunov.net/?p=364" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11" 0
In [6]:sample_string = 'koldunov.net 85.26.235.202 - - [16/Mar/2013:00:19:43 +0400] "GET /?p=364 HTTP/1.0" 200 65237 "http://koldunov.net/?p=364" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11" 0'
In [7]:data = p.parse(sample_string)
In [8]:data
Out[8]:
{'%>s': '200','%T': '0','%V': 'koldunov.net','%b': '65237','%h': '85.26.235.202','%i': 'http://koldunov.net/?p=364','%l': '-','%r': 'GET /?p=364 HTTP/1.0','%t': '[16/Mar/2013:00:19:43 +0400]','%u': '-','%{User-Agent}i': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'}

这就是解释器的工作。现在让我们加载真实世界的数据(示例文件位于这里和这里):

In [9]:log = open('access_log_for_pandas').readlines()

解析每一行,并且创建一个字典列表:

In [10]:
log_list = []
for line in log:try:data = p.parse(line)except:sys.stderr.write("Unable to parse %s" % line)data['%t'] = data['%t'][1:12]+' '+data['%t'][13:21]+' '+data['%t'][22:27]log_list.append(data)

我们不得不调整时间格式位,否则的话 pandas 将不能解析它。

创建和调整数据帧

这将创建一个字典列表,可以转化到一个数据帧:

import pandas as pd
import numpy as np
from pandas import Series, DataFrame, Panel
df = DataFrame(log_list)

展示数据帧的前两行:

df[0:2]
- %>s %T %V %b %h %i %l %r %t %u %{User-Agent}i
0 200 0 www.oceanographers.ru 26126 109.165.31.156 - - GET /index.php?option=com_content&task=section... 16/Mar/2013 08:00:25 +0400 - Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20...
1 200 0 www.oceanographers.ru 10532 109.165.31.156 http://www.oceanographers.ru/index.php?option=... - GET /templates/ja_procyon/css/template_css.css... 16/Mar/2013 08:00:25 +0400 - Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20...

我们不准备使用所有的数据,因此让我们删除一些列:

del df['%T']; del df['%V']; del df['%i']; del df['%l']; del df['%u']; del df['%{User-Agent}i']

并且把这些列重命名成人类可理解的格式:

df = df.rename(columns={'%>s': 'Status', '%b':'b', '%h':'IP', '%r':'Request', '%t': 'Time'})

结果数据帧的前 5 行:

df.head()
- Status b IP Request Time
0 200 26126 109.165.31.156 GET /index.php?option=com_content&task=section... 16/Mar/2013 08:00:25 +0400
1 200 10532 109.165.31.156 GET /templates/ja_procyon/css/template_css.css... 16/Mar/2013 08:00:25 +0400
2 200 1853 109.165.31.156 GET /templates/ja_procyon/switcher.js HTTP/1.0 16/Mar/2013 08:00:25 +0400
3 200 37153 109.165.31.156 GET /includes/js/overlib_mini.js HTTP/1.0 16/Mar/2013 08:00:25 +0400
4 200 3978 109.165.31.156 GET /modules/ja_transmenu/transmenuh.css HTTP/1.0 16/Mar/2013 08:00:25 +0400

转换时间列成 datetime 格式并做一个索引出来(pop 将丢弃原始的 Time 列):

df.index = pd.to_datetime(df.pop('Time'))

Status 变量是一个 string 类型,因此我们需要把它转换成 int:

df['Status'] = df['Status'].astype('int')

一些 b 列的行包含 '-' 字符,我们需要使用 astype 转换它们:

df['b'][93]
Out[19]:
'-'

我们可以为该列使用一个通用的函数,它们将把所有的破折号转换成 NaN,并且剩余的转换成 floats,另外把 bytes 转换成 megabytes:

def dash2nan(x):if x == '-':x = np.nanelse:x = float(x)/1048576.return x
df['b'] = df['b'].apply(dash2nan)

我相信有一个更优雅的方式来做到这一点。

流量分析

首先,最简单的散点:从该网站的出口流量:

df['b'].plot()
<matplotlib.axes.AxesSubplot at 0xbf7574c>

看起来在早上 9 点左右有人从网站下载了一些大的东西。

但是实际上你想知道的第一件事是你的网站有多少的访问量,以及它们的时间分布。我们从 b 变量的 5 分钟间隔重新取样,并计算每个时间跨度的请求数。实际上,在这个示例中不管我们使用哪个变量,这些数字将表明有多少次请求该网站的信息请求。

df_s = df['b'].resample('5t', how='count')
df_s.plot()
Out[23]:
<matplotlib.axes.AxesSubplot at 0xc14588c>

![此处输入图片的描述][8]

我们不仅仅计算每个时间的请求数,也计算每个时间段的总流量:

df_b = df['b'].resample('10t', how=['count','sum'])
df_b['count'].plot( color='r')
legend()
df_b['sum'].plot(secondary_y=True)
Out[24]:
<matplotlib.axes.AxesSubplot at 0xc2d53ac>

![此处输入图片的描述][9]

正如你所看到的,服务器请求数和流量是不一致的,相关性其实并不是非常高:

df_b.corr()

|-| count| sum
|count| 1.000000| 0.512629
|sum| 0.512629| 1.000000

我们可以仔细看下早高峰:

df_b['2013-03-16 6:00':'2013-03-16 10:00']['sum'].plot()
Out[26]:
<matplotlib.axes.AxesSubplot at 0xc3f5dac>

![此处输入图片的描述][10]

看起来流量峰值是由一个请求引起的。让我们找出这个请求。选择所有响应大于 20 Mb 的请求:

df[df['b']>20]
- Status b IP Request
Time
2013-03-16 09:02:59 200 21.365701 77.50.248.20 GET /books/Bondarenko.pdf HTTP/1.0

这是一本书的 pdf 文件,这就解释了在 2013-03-16 09:02:59 的流量出口峰值。

接近 20 Mb 是一个大的请求(至少对于我们网站),但是服务器响应的典型大小是?响应大小(小于 20Mb)的立方图看起来像这样:

cc = df[df['b']<20]
cc.b.hist(bins=10)
Out[28]:
<matplotlib.axes.AxesSubplot at 0xc52374c>

![此处输入图片的描述][11]

因此,大部分的文件是小于 0.5 Mb。实际上它们甚至更小:

cc = df[df['b']<0.3]
cc.b.hist(bins=100)
Out[29]:
<matplotlib.axes.AxesSubplot at 0xc5760ec>

![此处输入图片的描述][12]

使用 Pandas 分析 Apache 日志相关推荐

  1. 如何分析apache日志[access_log(访问日志)和error_log(错误日志)]

    如何分析apache日志[access_log(访问日志)和error_log(错误日志)] 发布时间: 2013-12-17 浏览次数:205 分类: 服务器 默认Apache运行会access_l ...

  2. kjb文件 解析_在Linux上使用lnav监控和分析Apache日志文件工具

    请关注本头条号,每天坚持更新原创干货技术文章. 如需学习视频,请在微信搜索公众号"智传网优"直接开始自助视频学习 1. 前言 本文主要讲解如何在Linux上使用lnav监控和分析A ...

  3. awstats mysql_Awstats分析apache日志

    Awstats分析apache日志 一.环境和软件 操作系统:CentOS release 5.4 软件:Apache/2.0.63awstats-6.95.tar.gzcronolog-1.6.2. ...

  4. elk系列7之通过grok分析apache日志

    preface 说道分析日志,我们知道的采集方式有2种: 通过grok在logstash的filter里面过滤匹配. logstash --> redis --> python(py脚本过 ...

  5. linux查看ip访问日志文件,linux分析apache日志获取最多访问的前10个IP

    apache日志分析可以获得很多有用的信息,现在来试试最基本的,获取最多访问的前10个IP地址及访问次数. 既然是统计,那么awk是必不可少的,好用而高效. 命令如下: awk '{a[$1] += ...

  6. nginx log response_python+pandas分析nginx日志的实例

    需求 通过分析nginx访问日志,获取每个接口响应时间最大值.最小值.平均值及访问量. 实现原理 将nginx日志uriuriupstream_response_time字段存放到pandas的dat ...

  7. python收入波动告警分析_使用Python/Pandas分析告警日志数据

    作者:吕磊 文章来自微信公众号:平台人生 Python Python是一种面向对象的解释型程序设计语言.作为一种脚本语言,Python在运行性能上相对C/C++等编译型语言有一定不足,但Python语 ...

  8. 如何在 Linux 上用 SQL 语句来查询 Apache 日志

    Linux 有一个显著的特点,在正常情况下,你可以通过日志分析系统日志来了解你的系统中发生了什么,或正在发生什么.的确,系统日志是系统管理员在解决系统和应用问题时最需要的第一手资源.我们将在这篇文章中 ...

  9. linux配置apache文件大小,linux下限制Apache日志access.log以及error.log文件大小

    如果网站开启了apache日志文件以及错误日志功能,那么很可能apache日志文件access.log在一段时间内就会很庞大至上百兆甚至几十个G,尤其大访问量的网站更是如此.error_log错误日志 ...

最新文章

  1. Matlab数据的可视化 -- 散点图
  2. 碰到故障大全---cd
  3. 给不爱洗手找个理由——皮肤共生菌可以促进伤口愈合
  4. 恩布开源安卓手机IM,EntboostIM发布1.5.2版本
  5. 小马智行Pony.ai 2020校招正式开启
  6. python propresql mysql_Python中操作mysql的pymysql模块详解
  7. windows server 2008 r2 IIS PHP
  8. BootstrapValidator验证
  9. PDG转PDF的方法
  10. 摈弃 Windows 低效率的工作方式,发掘 Linux 身上的 UNIX 气质
  11. FPGA时钟资源使用
  12. 内部排序比较(Java版)
  13. hdu 1003 Max Sum (DP)
  14. Java面试基础篇-Redis缓存
  15. [项目源码]ERP进销存系统
  16. Python分析成绩
  17. 屏蔽CSDN博客广告的油猴脚本
  18. Mac远程控制Ubuntu黑屏
  19. 阿里云盘正式上架,速度15MB/s!(附下载链接+阿里云盘邀请码)
  20. 关于小米公司成长的反思

热门文章

  1. 分布式是写出来的(五)
  2. c,c++中字符串处理函数strtok,strstr,strchr,strsub
  3. 【计算机系统设计】实践笔记(5)插叙:内外有别之CPU和Memory
  4. 【电路原理】学习笔记(0):电路与电路模型
  5. mmap内存映射、system V共享内存和Posix共享内存
  6. 一次违反常规的Java大厂面试经历,系列教学
  7. 搞懂开源框架设计思想真的这么重要吗?终获offer
  8. SQL常用日期处理函数(转)
  9. flask第一章:项目环境搭建
  10. Apache Tomcat 7 Configuration BIO NIO AIO APR ThreadPool