2012-09-22 20 views
24

Ho appena iniziato a imparare Python e vorrei leggere un file di registro Apache e inserire parti di ogni riga in elenchi diversi.Analisi dei file di registro apache

riga dal file

172.16.0.3 - - [25/Set/2002: 14: 04: 19 0200] "GET/HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv: 1.1) Gecko/20.020.827"

secondo Apache website formato è

% h% l% u% t \ "% r \ "%> s% b \"% {Referer} i \ "\"% {User-Agent} i \

Sono in grado di aprire il file e leggerlo come è ma non so come farlo leggere in quel formato in modo da poter inserire ciascuna parte in una lista.

+0

Quali elementi di questa linea ti interessano? (Tutti loro?) –

+0

mentre le linee cambiano leggermente Vorrei che fossero lette in quel formato esatto :) – ogward

+0

Hai frainteso - cosa intendo, cosa vuoi estrarre da ogni riga? Gli appuntamenti? IP? Tutto? –

risposta

33

Questo è un lavoro per regular expressions.

Ad esempio:

line = '172.16.0.3 - - [25/Sep/2002:14:04:19 +0200] "GET/HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827"' 
regex = '([(\d\.)]+) - - \[(.*?)\] "(.*?)" (\d+) - "(.*?)" "(.*?)"' 

import re 
print re.match(regex, line).groups() 

L'uscita sarebbe una tupla con 6 pezzi di informazioni dalla linea (in particolare, i gruppi tra parentesi a quel modello):

('172.16.0.3', '25/Sep/2002:14:04:19 +0200', 'GET/HTTP/1.1', '401', '', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827') 
+0

Questo sembra buono ma posso avere in qualche modo una "regex" per ogni parte? qualcosa di simile 'ip = '([(\ d \.)] +)' date = '.........' req = '........... .'' – ogward

+0

penso di aver capito. Grazie mille! – ogward

+1

Quando provo un'altra linea dal file, non funziona. ex ** 127.0.0.1 - stefan [01/Apr/2002: 12: 17: 21 +0200] "OTTI /sit3-shine.7.gif HTTP/1.1" 200 15811 "http: // localhost /" "Mozilla/5.0 (compatibile; Konqueror/2.2.2-2; Linux)" ** – ogward

12

Utilizzare un regolare espressione per dividere una riga in "token" separati:

>>> row = """172.16.0.3 - - [25/Sep/2002:14:04:19 +0200] "GET/HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827" """ 
>>> import re 
>>> map(''.join, re.findall(r'\"(.*?)\"|\[(.*?)\]|(\S+)', row)) 
['172.16.0.3', '-', '-', '25/Sep/2002:14:04:19 +0200', 'GET/HTTP/1.1', '401', '-', '', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827'] 

Un'altra soluzione è t o utilizzare uno strumento dedicato, ad es. http://pypi.python.org/pypi/pylogsparser/0.4

9

Ho creato una libreria Python che fa proprio questo: apache-log-parser.

>>> import apache_log_parser 
>>> line_parser = apache_log_parser.make_parser("%h <<%P>> %t %Dus \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %l %u") 
>>> log_line_data = line_parser('127.0.0.1 <<6113>> [16/Aug/2013:15:45:34 +0000] 1966093us "GET/HTTP/1.1" 200 3478 "https://example.com/" "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18)" - -') 
>>> pprint(log_line_data) 
{'pid': '6113', 
'remote_host': '127.0.0.1', 
'remote_logname': '-', 
'remote_user': '', 
'request_first_line': 'GET/HTTP/1.1', 
'request_header_referer': 'https://example.com/', 
'request_header_user_agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18)', 
'response_bytes_clf': '3478', 
'status': '200', 
'time_received': '[16/Aug/2013:15:45:34 +0000]', 
'time_us': '1966093'} 
7

RegEx sembrava estrema e problematico considerando la semplicità del formato, così ho scritto questo piccolo splitter che altri potrebbero trovare utile così:

def apache2_logrow(s): 
    ''' Fast split on Apache2 log lines 

    http://httpd.apache.org/docs/trunk/logs.html 
    ''' 
    row = [ ] 
    qe = qp = None # quote end character (qe) and quote parts (qp) 
    for s in s.replace('\r','').replace('\n','').split(' '): 
     if qp: 
      qp.append(s) 
     elif '' == s: # blanks 
      row.append('') 
     elif '"' == s[0]: # begin " quote " 
      qp = [ s ] 
      qe = '"' 
     elif '[' == s[0]: # begin [ quote ] 
      qp = [ s ] 
      qe = ']' 
     else: 
      row.append(s) 

     l = len(s) 
     if l and qe == s[-1]: # end quote 
      if l == 1 or s[-2] != '\\': # don't end on escaped quotes 
       row.append(' '.join(qp)[1:-1].replace('\\'+qe, qe)) 
       qp = qe = None 
    return row 
+0

Questo ha funzionato per me con Python 3. Avevo errori con l'altro Esempi di regex. Grazie. –

1

Aggiungi questa in httpd.conf per convertire l'apache registra a JSON.

LogFormat "{\"time\":\"%t\", \"remoteIP\" :\"%a\", \"host\": \"%V\", \"request_id\": \"%L\", \"request\":\"%U\", \"query\" : \"%q\", \"method\":\"%m\", \"status\":\"%>s\", \"userAgent\":\"%{User-agent}i\", \"referer\":\"%{Referer}i\" }" json_log 

CustomLog /var/log/apache_access_log json_log 
CustomLog "|/usr/bin/python -u apacheLogHandler.py" json_log 

Ora si vede access_logs in formato json. Usa il seguente codice Python per analizzare i log json che vengono costantemente aggiornati.

apacheLogHandler.py

import time 
f = open('apache_access_log.log', 'r') 
for line in f: # read all lines already in the file 
    print line.strip() 

# keep waiting forever for more lines. 
while True: 
    line = f.readline() # just read more 
    if line: # if you got something... 
    print 'got data:', line.strip() 
    time.sleep(1) 
0
import re 


HOST = r'^(?P<host>.*?)' 
SPACE = r'\s' 
IDENTITY = r'\S+' 
USER = r'\S+' 
TIME = r'(?P<time>\[.*?\])' 
REQUEST = r'\"(?P<request>.*?)\"' 
STATUS = r'(?P<status>\d{3})' 
SIZE = r'(?P<size>\S+)' 

REGEX = HOST+SPACE+IDENTITY+SPACE+USER+SPACE+TIME+SPACE+REQUEST+SPACE+STATUS+SPACE+SIZE+SPACE 

def parser(log_line): 
    match = re.search(REGEX,log_line) 
    return ((match.group('host'), 
      match.group('time'), 
         match.group('request') , 
         match.group('status') , 
         match.group('size') 
        ) 
        ) 


logLine = """180.76.15.30 - - [24/Mar/2017:19:37:57 +0000] "GET /shop/page/32/?count=15&orderby=title&add_to_wishlist=4846 HTTP/1.1" 404 10202 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)""" 
result = parser(logLine) 
print(result) 
Problemi correlati