【问题标题】:How to count accesses per hour from log file entries?如何从日志文件条目中计算每小时的访问次数?
【发布时间】:2018-01-30 12:53:02
【问题描述】:

我有一个日志文件,其中每一行都包含 IP 地址、访问时间和访问的 URL。我想统计每小时的访问次数。

访问数据的时间如下所示

[01/Jan/2017:14:15:45 +1000]
[01/Jan/2017:14:15:45 +1000]
[01/Jan/2017:15:16:05 +1000]
[01/Jan/2017:16:16:05 +1000] 

我怎样才能改进它,这样我就不需要为每个小时设置变量和 if 语句了?

twoPM = 0
thrPM = 0
fouPM = 0
timeStamp = line.split('[')[1].split(']')[0]
formated_timeStamp = datetime.datetime.strptime(timeStamp,'%d/%b/%Y:%H:%M:%S %z').strftime('%H')
if formated_timeStamp == '14':
    twoPM +=1
if formated_timeStamp == '15':
    thrPM +=1
if formated_timeStamp == '16':
    fouPM +=1

【问题讨论】:

  • 从 Code Review 迁移而来,因为它几乎不能“工作”,本质上问题是要求重写代码。

标签: python python-3.x parsing logging


【解决方案1】:
  1. 您可以在strptime 格式说明中包含方括号:

    datetime.datetime.strptime(line.strip(),'[%d/%b/%Y:%H:%M:%S %z]')
    
  2. 您可以使用任何datetime.datetime 对象的.hour 属性提取小时:

    timestamp = datetime.datetime.strptime(…)
    hour = timestamp.hour
    
  3. 您可以使用collections.Counter 计算元素的数量:

    from collections import Counter
    
    
    def read_logs(filename):
        with open(filename) as log_file:
             for line in log_file:
                 timestamp = datetime.datetime.strptime(
                         line.strip(),
                         '[%d/%b/%Y:%H:%M:%S %z]')
                 yield timestamp.hour
    
    
    def count_access(log_filename):
        return Counter(read_logs(log_filename))
    
    
    if __name__ == '__main__':
        print(count_access('/path/to/logs/'))
    

【讨论】:

    【解决方案2】:

    你可以使用字典:

    per_hour = {}
    per_hour[formated_timeStamp] += 1
    

    所以你会得到一些东西

    {'0': 12, '1': 8, '2': 41, ...}
    

    其中的键代表一个小时。

    【讨论】:

      【解决方案3】:

      您不会说每小时访问量是每天还是什么。所以有很多方法可以做到这一点。但这里有一个简单的版本:

      import collections
      import io
      
      log_data = '''
      [01/Jan/2017:14:15:45 +1000]
      [01/Jan/2017:14:15:45 +1000]
      [01/Jan/2017:15:16:05 +1000]
      [01/Jan/2017:16:16:05 +1000]
      '''
      
      def filter_lines(file):
          for line in file:
              if line.startswith('['):
                  yield line
      
      def extract_hour_from_line(seq):
          for line in seq:
              yield line.split(':')[1]
      
      def access_per_hour(file):
      
          aph = collections.Counter(extract_hour_from_line(filter_lines(file)))
          return aph
      
      
      if __name__ == '__main__':
          logfile = io.StringIO(log_data)
          aph = access_per_hour(logfile)
          print(aph)
      

      这使用 StringIO 将您作为示例提供的行转换为可以读取的内存“文件”。你可以打开你的日志文件,就像你已经在做的那样,正常处理这个问题。

      collections.Counter 类接受一个序列并生成一个类似字典的对象,其中键是序列中的项目,值是计数 - 每个项目在序列中出现的次数。

      这个版本的代码只计算所有不同的小时值,而不考虑访问发生在什么日期。也就是说,周二的 12:00 和周三的 12:00 被视为同一时间。如果您只是构建每小时需求的直方图,这将非常有用。

      如果您想进行更高级的分组,您可以尝试使用filter_lines 函数来限制您想要查看的总体上的行。例如,只有日期范围之间的行,或者只有访问特定 URL 的行。

      如果您想将不同的日子视为不同的,您可以使用extract_hour_from_line 函数来构造一个不同的值 - 例如,连接日期和小时。

      【讨论】:

        猜你喜欢
        • 2016-12-11
        • 1970-01-01
        • 2016-06-04
        • 2012-08-16
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        • 2013-12-08
        • 1970-01-01
        相关资源
        最近更新 更多