Làm cách nào để trích xuất địa chỉ IP xảy ra 10 lần trong khoảng thời gian một giây?Python: cách Phân tích cú pháp và kiểm tra thời gian?
Trong trường hợp sau đây:
241.7118.197.10
28.252.8
Làm cách nào để trích xuất địa chỉ IP xảy ra 10 lần trong khoảng thời gian một giây?Python: cách Phân tích cú pháp và kiểm tra thời gian?
Trong trường hợp sau đây:
241.7118.197.10
28.252.8
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ừ [
và \[
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ả.
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'])
để bạn đang đọc toàn bộ tệp? – Maria
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ó. –
Sử dụng hai dòng này, bạn sẽ cần hai mô-đun: 're' và' datetime' –
để mỗi 'dic [ip_addr]' chứa một hàng đợi? – Maria
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
có thể giải thích về 'r '(^ [^ \ s] *) [^ \ [] * \ [([^ \ s \]] *): (\ d +)'' – Maria