【问题标题】:Convert list of IPs to list of corresponding IP Ranges (python)将 IP 列表转换为相应 IP 范围的列表(python)
【发布时间】:2020-01-21 11:49:06
【问题描述】:

我想将 IP 列表转换为相应 IP 范围的列表。 例如:

iplist = ['137.226.161.121', '134.130.4.1', '137.226.161.149', '137.226.161.221', '137.226.161.240', '137.226.161.237', '8.8.8.8', '8.8.4.4', '137.226.161.189', '137.226.161.245', '137.226.161.172', '137.226.161.241', '137.226.161.234', '137.226.161.236', '134.130.5.1']

ipranges = ['137.226.161.0/24', '134.130.4.0/24', '8.8.8.0/24', '8.8.4.0/24', '134.130.5.0/24']

最有效的方法是什么?我还没有找到提供类似功能的模块。这个函数的原因是为了提高可读性,应该将一长串 IP(超过 1000 个 ip)转换为子网列表。

谢谢

【问题讨论】:

  • 是所有 IP 范围 /24,还是还有子网掩码?
  • 不管怎样,我会看看Built-in IP-Address 模块。

标签: python ip subnet


【解决方案1】:

如果我理解正确,您只想根据前 24 位 (/24) 相同的情况进行匹配。对于这些任务,我推荐set

iplist = ['137.226.161.121', '134.130.4.1', '137.226.161.149', '137.226.161.221', '137.226.161.240', '137.226.161.237', '8.8.8.8', '8.8.4.4', '137.226.161.189', '137.226.161.245', '137.226.161.172', '137.226.161.241', '137.226.161.234', '137.226.161.236', '134.130.5.1']

ipset = set()
for i in iplist:
    ipset.add(".".join(i.split(".")[:-1]))

ipranges = [p + ".0/24" for p in ipset]
print(ipranges)

这打印: ['134.130.5.0/24', '8.8.4.0/24', '8.8.8.0/24', '134.130.4.0/24', '137.226.161.0/24']

那么这段代码有什么作用呢?

首先,我们遍历列表,截断每个IP的最后一段:

segments = "8.8.8.8".split(".")  # segments == ["8", "8", "8", "8"]
segments_cut = segments[:-1]     # segments_cut == ["8", "8", "8"]
prefix = ".".join(segments_cut)  # prefix == "8.8.8"

现在我们将这些前缀添加到set。 Python set 只允许唯一元素。这导致:ìpset == {'134.130.5', '8.8.4', '8.8.8', '134.130.4', '137.226.161'}

最后我们遍历集合并附加后缀“.0/24”来表示子网。

编辑:关于“效率”

我喜欢answer by darkless,但只知道我的解决方案明显更快(1.2 秒对 0.09 秒):

>>> import timeit
>>> # darkless' ipaddress solution
>>> timeit.timeit("[str(ipaddress.ip_network('{}/24'.format(ip), strict=False)) for ip in iplist]", setup="import ipaddress;iplist = ['137.226.161.121', '134.130.4.1', '137.226.161.149', '137.226.161.221', '137.226.161.240', '137.226.161.237', '8.8.8.8', '8.8.4.4', '137.226.161.189', '137.226.161.245', '137.226.161.172', '137.226.161.241', '137.226.161.234', '137.226.161.236', '134.130.5.1']", number=10000)
1.186...
>>> # My solution
>>> timeit.timeit("[p + '.0/24' for p in {'.'.join(i.split('.')[:-1]) for i in iplist}]", setup="import ipaddress;iplist = ['137.226.161.121', '134.130.4.1', '137.226.161.149', '137.226.161.221', '137.226.161.240', '137.226.161.237', '8.8.8.8', '8.8.4.4', '137.226.161.189', '137.226.161.245', '137.226.161.172', '137.226.161.241', '137.226.161.234', '137.226.161.236', '134.130.5.1']", number=10000)
0.096...

【讨论】:

  • 这就是我想要的!谢谢
  • 我很高兴听到这个消息!
  • 关于效率的好消息;)对于 /24 范围(或 /8 /16 /32)确实可以更好地解决您的问题。
【解决方案2】:

正如 Hampus Larsson 所说,您可以使用 python ipaddress 模块:

import ipaddress

iplist = ['137.226.161.121', '134.130.4.1', '137.226.161.149', '137.226.161.221', '137.226.161.240', '137.226.161.237', '8.8.8.8', '8.8.4.4', '137.226.161.189', '137.226.161.245', '137.226.161.172', '137.226.161.241', '137.226.161.234', '137.226.161.236', '134.130.5.1']

ipranges = [str(ipaddress.ip_network('{}/24'.format(ip), strict=False)) for ip in iplist]

>>> ipranges
['137.226.161.0/24', '134.130.4.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '8.8.8.0/24', '8.8.4.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '137.226.161.0/24', '134.130.5.0/24']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-08
    • 2017-03-04
    • 1970-01-01
    • 2012-07-13
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多