在企业中,从日志中提取数据进行分析,可以帮助企业更加了解用户行为,用户最感兴趣的产品或者内容,分析得到数据后,可以决定企业在今后的走向。

从这些日志数据中,比较重要的有:

1. 用户访问最多的url,即用户在企业网站最感兴趣的产品或者内容

2. 用户群体的的主要线路是什么?移动?联通?电信?

3. 用户访问的高峰期是什么时候?最高PV(访问量)、UV(独立访客)、IP(独立IP)。

4. 各时段状态码数。比如304,表示静态资源在没有发生改变时,服务器要求客户使用了浏览器本地的缓存,可以降低服务器流量负载等。403、404如果异常得出现很多,则要根据访问得url来判断是否有恶意用户在对网站目录进行扫描和探测。400、500等状态码很多的情况就需要运维人员及时分析并排查原因。

5. 客户浏览器的名称、版本。统计出各种浏览器的分布情况,比如:如果手机浏览器、IE 6.0版本浏览器访问记录很多,则大概可以判断出用户群体大概的操作系统是winXP,win7以上版本,或是手机访问。那就需要考虑是否要对特定版本浏览器进行页面优化,或者如果客户是手机浏览器,那是否要压缩网站页面大小,降低流量消耗,亦或是否要对手机端优化,提升用户体验,牢牢得抓住客户。。

这里涉及部分SEO方面知识,仅作了解即可,如果企业真正需要了,再深入学习。

下面的例子对访问状态码和浏览器名称、版本进行了统计,以引出日志分析、数据挖掘的重要性:

  1. import datetime
  2. import re
  3. from queue import Queue
  4. import threading
  5. from pathlib import Path
  6. from user_agents import parse
  7. from collections import defaultdict
  8.  
  9. # 正则,文件读取,时间窗口,队列,多线程,高阶函数,分发器,嵌套函数
  10.  
  11. logline = '''183.60.212.153 - - [19/Feb/2013:10:23:29 +0800] "GET /o2o/media.html?menu=3 HTTP/1.1" 200 16691 "-" "Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)"'''
  12.  
  13. pattern = '''(?P<remote_addr>[\d\.]{7,}) - - (?:\[(?P<datetime>[^\[\]]+)\]) "(?P<request>[^"]+)" (?P<status>\d+) (?P<size>\d+) "[^"]+" "(?P<useragent>[^"]+)"'''
  14.  
  15. # 数据源处理
  16. ops = {
  17. 'datetime': lambda timestr: datetime.datetime.strptime(timestr, "%d/%b/%Y:%H:%M:%S %z"),
  18. 'request': lambda request: dict(zip(('method', 'url', 'protocol'), request.split())),
  19. 'status': int,
  20. 'size': int,
  21. 'useragent': lambda useragent: parse(useragent)
  22. }
  23.  
  24. regex = re.compile(pattern)
  25.  
  26. def extract(line):
  27. matcher = regex.match(line)
  28. if matcher:
  29. return {k: ops.get(k, lambda x: x)(v) for k, v in matcher.groupdict().items()}
  30.  
  31. def openfile(path:str):
  32. with open(path) as f:
  33. for line in f:
  34. fields = extract(line)
  35. if fields:
  36. yield fields # return generator objects,next(load(path))
  37. else:
  38. # TODO 不合格数据有哪些
  39. continue # TODO 解析失败就抛弃,或者打印日志
  40.  
  41. def load(*paths):
  42. '''装载日志文件或路径'''
  43. for item in paths:
  44. p = Path(item)
  45. if not p.exists():
  46. continue
  47.  
  48. if p.is_dir():
  49. for file in p.iterdir():
  50. if file.is_file():
  51. yield from openfile(str(file))
  52. elif p.is_file():
  53. yield from openfile(str(p))
  54.  
  55. def window(src:Queue, handler, width: int, interval: int):
  56. '''
  57. 窗口函数
  58. :param src: 数据源,生成器,用来拿数据
  59. :param handler: 数据处理函数
  60. :param width: 时间窗口宽度,秒
  61. :param interval: 处理时间间隔,秒/ 时间偏移量,秒
  62. :return:
  63. '''
  64.  
  65. start = datetime.datetime.strptime('1970/01/01 01:01:01 +0800', '%Y/%m/%d %H:%M:%S %z')
  66. current = datetime.datetime.strptime('1970/01/01 01:01:02 +0800', '%Y/%m/%d %H:%M:%S %z')
  67. delta = datetime.timedelta(seconds=width-interval)
  68.  
  69. buffer = [] #窗口里的待计算数据
  70.  
  71. while True: #while True方式迭代queue
  72. # 从数据源获取数据
  73. data = src.get() # block阻塞的
  74.  
  75. if data:
  76. buffer.append(data)
  77. current = data['datetime']
  78.  
  79. if (current - start).total_seconds() >= interval:
  80. ret = handler(buffer) # 如何处理
  81. print("{}".format(ret))
  82.  
  83. start = current
  84.  
  85. buffer = [i for i in buffer if i['datetime'] > current - delta]
  86.  
  87. def donothing_handler(iterable:list):
  88. # print(iterable)
  89. return iterable
  90.  
  91. # 状态码时间段百分比分析
  92. def status_handler(iterable:list):
  93. d = {}
  94. for item in iterable:
  95. key = item['status']
  96. if key not in d:
  97. d[key] = 0
  98. d[key] += 1
  99.  
  100. total= sum(d.values())
  101. return {'{}: {:.2f}%'.format(k,v/total*100) for k,v in d.items()}
  102.  
  103. # 浏览器分析函数
  104. ua_dict = defaultdict(lambda : 0) # 作用域改为全局之后,字典递增保存所有ua及其版本
  105. def browser_handler(iterable):
  106. for item in iterable:
  107. ua = item['useragent']
  108. key = (ua.browser.family, ua.browser.version_string)
  109. ua_dict[key] += 1
  110. return ua_dict
  111.  
  112. # 分发器,嵌套函数
  113. def dispatcher(src):
  114. queues = [] # 队列列表
  115. threads = [] # 线程管理
  116.  
  117. def reg(handler, width, interval):
  118. q = Queue() # 分配队列
  119. queues.append(q) # 方便调用
  120.  
  121. t = threading.Thread(target=window,args=(q, handler, width, interval))
  122. threads.append(t)
  123.  
  124. def run():
  125. for t in threads:
  126. t.start()
  127.  
  128. for x in src:
  129. for q in queues:
  130. q.put(x)
  131.  
  132. return reg,run
  133.  
  134. reg,run = dispatcher(load('test.log'))
  135.  
  136. # reg注册 窗口
  137. # reg(donothing_handler, 10, 5) #注册测试
  138. # reg(status_handler, 10, 5) # 注册状态码处理函数
  139. reg(browser_handler, 60, 60) # 注册useragent处理函数,注意时间窗口宽度
  140.  
  141. run()

  

Python 日志处理(三) 日志状态码分析、浏览器分析的更多相关文章

  1. 利用python完成多个url状态码的检测

    import re import requests import json from threading import Thread,Lock from concurrent.futures impo ...

  2. HTTP协议图--HTTP 响应状态码(重点分析)

    1. 状态码概述 HTTP 状态码负责表示客户端 HTTP 请求的返回结果.标记服务器端的处理是否正常.通知出现的错误等工作. HTTP 状态码如 200 OK ,以 3 位数字和原因短语组成.数字中 ...

  3. HTTP学习记录:三、状态码

    学习资源主要为:@小坦克HTTP相关博客 常见的HTTP状态码: 200--请求成功: 302--重定向: 304--Not Modified:表示上次的文档已经被缓存了,还可以继续使用: 400-- ...

  4. python 使用异常代替返回状态码

  5. (转)Python 日志处理(三) 日志状态码分析、浏览器分析

    原文:https://www.cnblogs.com/i-honey/p/7791564.html 在企业中,从日志中提取数据进行分析,可以帮助企业更加了解用户行为,用户最感兴趣的产品或者内容,分析得 ...

  6. nginx 499状态码

    Web服务器在用着nginx,在日志中偶尔会看到有499这个错误. rfc2616中,400-500间的错误码仅定义到了417,所以499应该是nginx自己定义的.后来想到读读nginx代码,疑问立 ...

  7. Nginx_HTTP 499 状态码 nginx下 499错误

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

  8. HTTP 499 状态码 nginx下 499错误[转]

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

  9. HTTP 499 状态码 nginx下 499错误

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

随机推荐

  1. Spring MVC Ajax 嵌套表单数据的提交

    概述 在一些场景里,某个大表单里常常嵌套着一个或若干个小逻辑块,比如以下表单里"设计预审"中包括了一个子模块表单"拟定款项". 在这种情况下该怎么去设计实体类以 ...

  2. Intel Core Microarchitecture Pipeline

    Intel微处理器近20年从Pentium发展到Skylake,得益于制作工艺上的巨大发展,处理器的性能得到了非常大的增强,功能模块增多,不过其指令处理pipeline的主干部分算不上有特别大的变化, ...

  3. UWP 分享用那个图标

    有两个图标,如果让你选,你会用哪个图标做分享图标? 这就算有意义的图标和通用图标的选择. 可以看到 左边的图标比较有意义,但是右边的图标是通用的. 是需要选有意义的?还是通用的 在 UWP ,选的是第 ...

  4. asp.net C# 实现微信服务器配置

    微信服务器配置接收页面示例代码 /// <summary> /// 微信的Token /// </summary> const string Token = "Tok ...

  5. cocoapods导入第三方库提示RPC failed curl 18 transfer

    错误提示: error: RPC failed; curl 18 transfer closed with outstanding read data remaining fatal: The rem ...

  6. JAVA描述的简单ORM框架

    抽了点时间自己写了个ORM,主要是为了复习JAVA泛型,映射,注解方面的知识.如需代码,可前往:https://github.com/m2492565210/java_orm自行下载 框架的类结构如下 ...

  7. [ACdream]小晴天老师系列——竖式乘

    题目链接:http://acdream.info/contest?cid=1269#problem-C Problem Description 小晴天是ACdream团队中最牛的老师之一,他最擅长数学 ...

  8. css3中“渐变”兼容性解决方案

    这次是简单的谈一下我们常见的渐变在各个浏览器下的兼容性问题,算一个比较简单的问题. 我们熟知的浏览器有Chrome.Firefox.Opera.Safari以及ie系列.最基础的background: ...

  9. 基于vip和twemproxy代理实现redis集群的无感知弹性扩容

    目标是实现redis集群的无感知弹性扩容 关键点 1是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量. 最原始的twe ...

  10. 一个简单大方的赞后+1,踩后-1js动画效果

    js部分 <script type="text/javascript"> <!-- $(document).ready(function(e) { $('a.zh ...