2016-12-24 36 views

Trả lời

5

Bạn có thể thu thập dữ liệu để dict nơi IP là khóa và giá trị chứa dấu thời gian cho IP đã cho. Sau đó, mỗi khi timestamp được thêm vào, bạn có thể kiểm tra xem IP nhất định có ba timestamps trong vòng một giây:

from datetime import datetime, timedelta 
from collections import defaultdict, deque 
import re 

THRESHOLD = timedelta(seconds=1) 
COUNT = 3 

res = set() 
d = defaultdict(deque) 

with open('test.txt') as f: 
    for line in f: 
     # Capture IP and timestamp 
     m = re.match(r'(\S*)[^\[]*\[(\S*)', line) 
     ip, dt = m.groups() 

     # Parse timestamp 
     dt = datetime.strptime(dt, '%d/%b/%Y:%H:%M:%S:%f') 

     # Remove timestamps from deque if they are older than threshold 
     que = d[ip] 
     while que and (dt - que[0]) > THRESHOLD: 
      que.popleft() 

     # Add timestamp, update result if there's 3 or more items 
     que.append(dt) 
     if len(que) >= COUNT: 
      res.add(ip) 

print(res) 

Kết quả:

{'28.252.89.140'} 

Trên đọc logfile chứa dòng nhật ký của dòng. Đối với mỗi dòng, cụm từ thông dụng được sử dụng để thu thập dữ liệu theo hai nhóm: IP và dấu thời gian. Sau đó, strptime được sử dụng để phân tích cú pháp thời gian.

Nhóm đầu tiên (\S*) ghi lại mọi thứ trừ khoảng trắng. Sau đó, [^\[]* chụp mọi thứ ngoại trừ [\[ chụp ký tự cuối cùng trước dấu thời gian. Cuối cùng, (\S*) được sử dụng lại để ghi lại mọi thứ cho đến khoảng trắng tiếp theo. Xem example on regex101.

Khi chúng tôi có IP và thời gian chúng được thêm vào defaultdict trong đó IP được sử dụng làm khóa và giá trị là deque của dấu thời gian. Trước khi dấu thời gian mới được thêm vào, dấu thời gian cũ sẽ bị xóa nếu chúng cũ hơn THRESHOLD. Điều này giả định rằng các dòng log đã được sắp xếp theo thời gian. Sau khi bổ sung độ dài được kiểm tra và nếu có COUNT hoặc nhiều mục trong IP hàng đợi được thêm vào tập kết quả.

+0

để mỗi 'dic [ip_addr]' chứa một hàng đợi? – Maria

+0

Có, 'deque' của dấu thời gian từ nơi các mục cũ nhất có thể bị xóa mỗi khi dấu thời gian mới được thêm vào. – niemmi

+0

có thể giải thích về 'r '(^ [^ \ s] *) [^ \ [] * \ [([^ \ s \]] *): (\ d +)'' – Maria

3

Bước đầu tiên sẽ được phân tích dữ liệu, bạn có thể làm như vậy với điều này:

data = [(ip, datetime.strptime(time, '%d/%b/%Y:%H:%M:%S:%f')) for (ip, time) in re.findall("((?:[0-9]{1,3}\.){3}[0-9]{1,3}).+?\[(.+?) -", text)] 

trong đó text là văn bản đầu vào.

Điều này sẽ trả về danh sách với một bộ dữ liệu cho mỗi mục nhập. Yếu tố đầu tiên của tuple sẽ là địa chỉ ip, thứ hai ngày.

Bước tiếp theo là để xem cái nào xảy ra trong một khoảng thời gian 1 giây và có ip giống nhau:

print set([a[0] for a in data for b in data for c in data if (datetime.timedelta(seconds=0)<a[1]-b[1]<datetime.timedelta(seconds=1)) and (datetime.timedelta(seconds=0)<a[1]-c[1]<datetime.timedelta(seconds=1)) and (datetime.timedelta(seconds=0)<b[1]-c[1]<datetime.timedelta(seconds=1))]) 

Output:

set(['28.252.89.140']) 
+0

để bạn đang đọc toàn bộ tệp? – Maria

+0

Tệp nào? Bạn chỉ xác định rằng văn bản đầu vào. Nếu văn bản đó nằm trong một tệp, trước tiên bạn nên đọc nó. –

+0

Sử dụng hai dòng này, bạn sẽ cần hai mô-đun: 're' và' datetime' –

Các vấn đề liên quan