Не используя библиотеки для парсинга, распарсить файл логов web-сервера
Python. Не используя библиотеки для парсинга, распарсить файл логов web-сервера В файле лого содержатся строки:
93.180.71.3 - - [17/May/2015:08:05:32 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
93.180.71.3 - - [17/May/2015:08:05:23 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
80.91.33.133 - - [17/May/2015:08:05:24 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.17)"
Необходимо получить список кортежей вида: (<remote_addr>, <request_type>,<requested_resource>)
Как пример:
[
...
('141.138.90.60', 'GET', '/downloads/product_2'),
('141.138.90.60', 'GET', '/downloads/product_2'),
('173.255.199.22', 'GET', '/downloads/product_2'),
...
]
Писал:
import re
def reader(filename):
regexp = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
with open(filename) as f:
log = f.read()
ips_list = re.findall(regexp, log)
print(ips_list)
if __name__ == '__main__':
reader('nginx_logs.txt')
Пробовал через regexp получить данные (в коде выше):
regexp = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
Но это получает только IP, а следующив тип запроса и куда обращались не вытягивает. Как можно получить данные в виде кортежей?
Ответы (3 шт):
Можно даже без регулярных выражений
def parse_log_line(log_line: str):
ip_address, log_line = log_line.split(' - - ')
date, log_line = log_line.split('] ')
# Удаление символа [ из строки даты
date = date.lstrip('[')
request, other_info = log_line.rsplit(' "-" ')
# Удаление символа " из строки прочей информации
other_info = other_info.strip('"')
# Удаление символа " из строки запроса
request = request.replace('"', '').split(' ')
return ip_address, date, *request, other_info
lines = ['93.180.71.3 - - [17/May/2015:08:05:32 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"',
'93.180.71.3 - - [17/May/2015:08:05:23 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"',
'80.91.33.133 - - [17/May/2015:08:05:24 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.17)"']
parsed_lines = [parse_log_line(line) for line in lines]
Вообще тут можно одними split обойтись, пользуясь тем фактом, что в указанных в данных полях не может быть пробелов:
data = """
93.180.71.3 - - [17/May/2015:08:05:32 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
93.180.71.3 - - [17/May/2015:08:05:23 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.21)"
80.91.33.133 - - [17/May/2015:08:05:24 +0000] "GET /downloads/product_1 HTTP/1.1" 304 0 "-" "Debian APT-HTTP/1.3 (0.8.16~exp12ubuntu10.17)"
"""
result = [(lambda x: (x[0],x[5][1:],x[6]))(line.split()) for line in data.split('\n') if line]
print(result)
Вывод:
[('93.180.71.3', 'GET', '/downloads/product_1'), ('93.180.71.3', 'GET', '/downloads/product_1'), ('80.91.33.133', 'GET', '/downloads/product_1')]
Можно использовать библиотеку Fabric, которая позволяет выполнять обычные Linux команды на удаленной сервере.
Например, получить все логи с сервера. Оставить только первый столбец (то есть IP адрес) и отсортировать их.
from fabric import Connection
server_nginx = Connection(
'192.168.X.X',
user='root'
)
list_address: list[str] = server_nginx.run(
command="cat /var/log/nginx/access.log | awk '{print $1}' | sort -u",
hide=True
).stdout.split("\n")
print(list_address)