我有一个像这样读取的CSV文件:
with open(r"file.csv", 'rb') as f:
reader = csv.reader(f)
c = list(reader)
此操作产生了大约22000个其他列表的1个列表。格式为:
[['10.0.0.0/24', 'random bla', 'vlan=22'], ['20.0.0.0/20', 'random bla 2', vlan=354] ...x22000]
这是一个只包含网络,vlan,描述等的IP数据库。我制作了一个脚本来检查数据库中是否存在任意输入。对于我需要在数据库中检查的每个网络,我需要执行以下操作:
我对你的要求是:我怎样才能加快速度?我不能简单地做“if my_ip in csv_database”,因为我需要它们是IPNetwork对象,所以例如10.0.0.1匹配,如果面对10.0.0.0/24,因为该IP在网络范围内。
答案 0 :(得分:2)
目前,您在检查IP之前将所有网络加载到内存中,但实际上并不需要这样做,您只需迭代读取器而不是将其转换为列表。
相反,我会加载所有IP地址以检查列表并对它们进行排序。然后可以使用bisect
以对数时间从列表中获取单个网络中的所有IP,因此不是O(m*n)
而是O(m*log(n))
,而是排序成本地址列表。
应该与此类似*:
from bisect import bisect_left, bisect_right
def find_ips_in_network(network, sorted_ips):
first = netaddr.IPAddress(network.first)
last = netaddr.IPAddress(network.last)
first_idx = bisect_left(sorted_ips, first)
last_idx = bisect_right(sorted_ips, last)
return sorted_ips[first_idx:last_idx]
sorted_ips = sorted(...) # load ips as sorted list of netaddr.IPAddress
found_networks = dict()
# or collections.defaultdict(list) if you want all networks
with open(r"file.csv", 'rb') as f:
reader = csv.reader(f)
for row in reader:
network = netaddr.IPNetwork(row[0])
for ip in find_ips_in_network(network, sorted_ips):
found_networks[ip] = row
# or found_networks[ip].append(row) if using defaultdict
for ip in sorted_ips:
if ip in found_networks:
print ip, "found in:", found_networks[ip]
*免责声明:无法保证正确性
编辑:小优化:由于首先计算第一个地址的索引,因此可以在搜索最后一个索引时限制下限:
last_idx = bisect_right(sorted_ips, last, first_index)
说明: bisect_left
和bisect_right
使用binary search搜索已排序列表中的给定值,并返回值必须具有的索引插入到主菜单列表的排序。 bisect_left
和bisect_right
之间的区别在于值已经在列表中(一次或多次),bisect_left
将返回第一个匹配的索引{{1最后一个+ 1的索引
所以在这种情况下:
bisect_right
将返回first_idx = bisect_left(sorted_ips, first)
的第一个IP地址的索引,该索引大于或等于sorted_ips
,并且
first
在最后一个IPAddress小于或等于last_idx = bisect_right(sorted_ips, last, first_idx)
之后返回一个索引。
我们知道last
,first <= last
必须为fist_idx
,因此第二次搜索的下限可以限制为<= last_idx
。
这意味着切片first_idx
包含sorted_ips[first_idx:last_idx]
列表中的所有IP。如果列表中的地址不相等或者在first <= ip <= last
和first
之间,则两个索引都相同,返回一个空列表。
由于二进制搜索的最差情况是last
,因此查找列表中的哪些IP在网络中然后检查所有IP的所有网络,特别是如果要检查的IP列表,这将快得多非常大。