代码之家  ›  专栏  ›  技术社区  ›  Amit Singh Parihar

如何从web服务器日志文件中提取数据,并解析请求行部分?

  •  2
  • Amit Singh Parihar  · 技术社区  · 10 年前

    下面给出了我试图从中提取信息的行的示例。

    [02/Jan/2015:08:07:32] "GET /click?article_id=162&user_id=5475 HTTP/1.1" 200 4352
    [02/Jan/2015:08:08:43] "GET /click?article_id=139&user_id=19550 HTTP/1.1" 200 3078
    [02/Jan/2015:08:09:01] "GET /click?article_id=87&user_id=9408 HTTP/1.1" 200 2005
    [02/Jan/2015:08:09:18] "GET /click?article_id=175&user_id=9408 HTTP/1.1" 200 3467
    

    我尝试了两种方法。其中一个是

    with open('C:/Users/.../access_log/access.log', 'r') as read:      
       for line in read:
          if "click?" in line:
              article_id = line.split('article_id=')[1]
              user_id = line.split('user_id=')[1]
              article.write(article_id)
              user.write(user_id)
    

    我需要提取 date , article_id , author_id 以及最后两组数字。通过使用上面的代码,我的输出如下所示

    对于user_id文件,输出如下

      5475 HTTP/1.1" 200 4352
    

    这里5475是我需要的id,但行的其余部分都附带了它。类似于 文章id 文件输出如下

       162&user_id=5475 HTTP/1.1" 200 4352
    

    这里162是我需要的值,但我再次用这个值得到行的其余部分。

    我尝试的第二种方法是

    for line in read:
       article_id = re.match('.*article_id=(\d+)', line)
       user_id = re.match('.*user_id=(\d+)', line)
       if article_id and article_id.lastindex > 0:
           ids.write(article_id.group(1))
    

    然后我得到这样的输出

      1621398717554254614225905016411314518885592112332
    

    我无法在excel中执行此操作,因为excel要处理的数据点太多,所有文件都无法正确加载。此外,我需要确保在提取数据点时( 日期 , 文章id , 作者id ,…),每个数据点对应于同一行的另一个数据点,这样我就可以看到是否有丢失的值。

    本质上,我有没有办法扭转这种局面

    [02/Jan/2015:08:07:32]“获取/点击?article_id=162&user_id=5475 HTTP/1.1”200 4352
    [02/Jan/2015:08:08:43]“获取/点击?article_id=139&user_id=19550 HTTP/1.1”200 3078
    [02/Jan/2015:08:09:01]“获取/点击?article_id=87&user_id=9408 HTTP/1.1”200 2005
    [02/Jan/2015:08:09:18]“获取/点击?article_id=175&user_id=9408 HTTP/1.1”200 3467
    

    进入这个

          Date                   Article_id    user_id       Response_code  Content size
    
          02/Jan/2015:08:07:32   162           5475          200            4352                     
          02/Jan/2015:08:08:43   139           19950         200            3078
    
    4 回复  |  直到 10 年前
        1
  •  3
  •   midori    10 年前

    您可以使用这个简单的正则表达式来拆分行:

    re.split(r' ".*?=|&.*?=| .*?" ', line)
    

    输出:

    ['[02/Jan/2015:08:07:32]', '162', '5475', '200 4352']
    

    您还可以使用 findall :

    re.findall(r'\[(.*?)\].*?(\d+).*?(\d+).*?(\d+)\s(\d+)', line)
    

    输出:

    [('02/Jan/2015:08:07:32', '162', '5475', '200', '4352')]
    

    您可以指定 re.findall 变量并使用对元素的简单访问,例如:

    data = re.findall(r'\[(.*?)\].*?(\d+).*?(\d+).*?(\d+)\s(\d+)', line)
    print data[0][0]
    02/Jan/2015:08:07:32
    

    注: 如果缺少任何值,你会看到它,但我的解决方案不会告诉你具体缺少哪一个。

        2
  •  1
  •   MaxU - stand with Ukraine    10 年前

    试试这个:

    from __future__ import print_function
    import re
    
    parse_re = r'\[([^\[\]]*)\]\s+.*?article_id=(\d+).*?user_id=(\d+)[^\"]*?\"\s+(\d+)\s+(\d+)'
    
    with open('apache.log', 'r') as f:
        data = f.readlines()
    
    for line in data:
        m = re.match(parse_re, line)
        if m:
            (date, article_id, user_id, response_code, content_size) =m.groups()
            print(date, article_id, user_id, response_code, content_size)
    

    输出:

    02/Jan/2015:08:07:32 162 5475 200 4352
    02/Jan/2015:08:08:43 139 19550 200 3078
    02/Jan/2015:08:09:01 87 9408 200 2005
    02/Jan/2015:08:09:18 175 9408 200 3467
    
        3
  •  0
  •   Bangi    10 年前

    @阿米特:我有下面的代码

    import re
    a='[02/Jan/2015:08:07:32] "GET /click?article_id=162&user_id=5475 HTTP/1.1" 200 4352 '
    
    for line in a:
        match =  re.search("\[(\d+\/[A-Za-z]+\/\d+\:\d+\:\d+\:\d+)\] \"GET\/click\article_id\=(\d+)\&user_id\=(\d+) HTTP\/1\.1\" (\d+) (\d+)",line)
        if match: 
             print "%s   %s  %s %s %s  " %( match.group(1), match.group(2), match.group(3), match.group(4), match.group(5) )
    
    output 
    02/Jan/2015:08:07:32   162  5475 200 4352
    
        4
  •  0
  •   Ethan Furman    10 年前

    为了解析 GET 片段,并能够判断片段何时丢失,一个小功能将完成这项工作:

    def extract_get_fields(line):
        # fields should be a list desired field names
        if 'GET' not in line:
            return None
        result = {}
        line = line.split('GET ', 1)[1]
        line = line.rsplit('"', 1)[0]
        line = line.rsplit(None, 1)[0]
        # line is now the segment between GET and the last double quote
        result['page'], crumbs = line.split('?')
        for crumb in crumbs.split('&'):
            name, value = crumb.split('=')
            result[name] = value
        return result
    

    以及在使用中:

    # second and third lines are missing pieces
    data = [
        '[02/Jan/2015:08:07:32] "GET /click?article_id=162&user_id=5475 HTTP/1.1" 200 4352',
        '[02/Jan/2015:08:08:43] "GET /click?article_id=139 HTTP/1.1" 200 3078',
        '[02/Jan/2015:08:09:01] "GET /click?user_id=9408 HTTP/1.1" 200 2005',
        '[02/Jan/2015:08:09:18] "GET /click?article_id=175&user_id=9408 HTTP/1.1" 200 3467',
        ]
    
    for line in data:
        result = extract_get_fields(line)
        if result is None:
            # wasn't a GET line, skip it
            continue
        if result['page'] != '/click':
            # wasn't a click page, skip it
            continue
        article_id = result.get('article_id', '')
        user_id = result.get('user_id', '')
        print('article_id: %5s   user_id: %s' % (article_id, user_id))
    

    这导致:

    article_id:   162   user_id: 5475
    article_id:   139   user_id: 
    article_id:         user_id: 9408
    article_id:   175   user_id: 9408
    

    注意:您需要增强和/或与其他答案结合,才能获得 date 以及其他领域。