使用 python,查看大约一百万个 IP 地址中哪个适合三个 cidr 的最快方法是什么?

Using python, what's the fastest way to see which of around one million ip addresses fit into three cidrs?

我有一个大约 1,000,000 个 IP 地址字符串的列表。我想获取三个 cidr 中的这些 ip 地址的集合(每个 cidr 都是这样的字符串:“1.0.0.0/25”)。最快的方法是什么?

A) 将三个cidrs 转换成包含cidrs 中包含的所有ip 地址的集合。对于我列表中的每个 IP 地址,我检查该 IP 地址是否在想要的 IP 地址集中。

B) 将每个 cidr 转换为最小和最大 ip 地址。将每个 ip 地址转换为整数元组并检查 ip > min 和 ip < max.

如果您使用 Python 3.3 或更高版本,一个不错的解决方案是使用 the ipaddress module。将您的 CIDR 转换为预先使用 ipaddress.ip_network 的网络对象,然后将您的地址转换为地址对象(如果它们可能是 IPv4 或 IPv6,则使用 ipaddress.ip_address,或者只是 ipaddress.IPv4Address/ipaddress.IPv6Address如果它们是已知类型则直接(跳过一层包装)。

您可以使用 in 运算符相对便宜地测试成员资格,例如如果您按顺序存储您的网络(例如 list/tuple),您可以这样做:

for address in map(ipaddress.ip_address, stream_of_string_addresses):
    if any(address in network for network in networks):
        ... got a match ...

有更有效的解决方案(特别是如果您谈论的是多个网络,而不仅仅是三个),但这很简单,内存效率相对较高,并且为您留下了一个有用的对象(不仅仅是原始地址字符串)进行进一步处理。

如果您只有 3 个 CIDR,只需编写三个临时函数,例如:

def test_cidr1(ipstr):
    # example for 192.168.128.0/18 (i.e. netmask 255.255.192.0)
    if not ipstr.startswith('192.168.'):
        return False
    ip0, ip1, ip2, ip3 = ipstr.split('.')
    return int(ip2) & 192 == 128