【问题标题】:How can I generate all possible IPs from a list of ip ranges in Python?如何从 Python 中的 IP 范围列表中生成所有可能的 IP?
【发布时间】:2013-07-12 13:33:37
【问题描述】:

假设我有一个文本文件包含一堆这样的 ip 范围:

x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y
x.x.x.x-y.y.y.y

x.x.x.x 是起始值,y.y.y.y 是范围的结束值。

如何在 python 的新文本文件中将这些 IP 范围转换为所有可能的 IP?

PS:这个问题和我之前的任何问题都不一样。我在上一个问题中问过“如何从 cidr 符号生成所有可能的 ips”。但是在这里我问“如何从ip范围列表生成”。这些是不同的东西。

【问题讨论】:

  • 它只是一个IPv4 地址的文件吗?或者那里也有IPv6s?

标签: python ip converter generator cidr


【解决方案1】:

仅适用于 IPv4 的 Python 3,与 @User 的想法相同,但使用新的 Python3 标准库:ipaddress

IPv4 由 4 个字节表示。所以next IP其实就是next number,一个IP范围可以表示为一个整数范围。

0.0.0.1 是 1

0.0.0.2 是 2

...

0.0.0.255 是 255

0.0.1.0 是 256

0.0.1.1 是 257

按代码(忽略 In []: 和 Out []:)

In [68]: from ipaddress import ip_address

In [69]: ip_address('0.0.0.1')
Out[69]: IPv4Address('0.0.0.1')

In [70]: ip_address('0.0.0.1').packed
Out[70]: b'\x00\x00\x00\x01'

In [71]: int(ip_address('0.0.0.1').packed.hex(), 16)
Out[71]: 1

In [72]: int(ip_address('0.0.1.0').packed.hex(), 16)
Out[72]: 256

In [73]: int(ip_address('0.0.1.1').packed.hex(), 16)
Out[73]: 257

ip.packed.hex() 返回 4 个字节的十六进制形式,因为它在 十六进制,它更短(例如:0xff 十六进制 == 255 十进制 == 0b11111111 二进制), 因此,通常用于表示字节。 int(hex, 16) 返回整数值 对应十六进制值,更人性化,可以作为ip_address的输入。

from ipaddress import ip_address

def ips(start, end):
    '''Return IPs in IPv4 range, inclusive.'''
    start_int = int(ip_address(start).packed.hex(), 16)
    end_int = int(ip_address(end).packed.hex(), 16)
    return [ip_address(ip).exploded for ip in range(start_int, end_int)]


ips('192.168.1.240', '192.168.2.5')

返回:

['192.168.1.240',
 '192.168.1.241',
 '192.168.1.242',
 '192.168.1.243',
 '192.168.1.244',
 '192.168.1.245',
 '192.168.1.246',
 '192.168.1.247',
 '192.168.1.248',
 '192.168.1.249',
 '192.168.1.250',
 '192.168.1.251',
 '192.168.1.252',
 '192.168.1.253',
 '192.168.1.254',
 '192.168.1.255',
 '192.168.2.0',
 '192.168.2.1',
 '192.168.2.2',
 '192.168.2.3',
 '192.168.2.4']

【讨论】:

  • 请注意,这种方法不包括 ip 范围的末尾。这将产生[] 的范围,例如1.1.1.1 - 1.1.1.1,而不是可能预期的['1.1.1.1']。为了包容,将列表理解中的范围更改为range(start_int, end_int + 1)
【解决方案2】:

试试这个:

def ip_range(start_ip,end_ip):
start = list(map(int,start_ip.split('.')))
end = list(map(int,end_ip.split('.')))
iprange=[]
while start!=list(map(int,end_ip.split('.'))):
    for i in range(len(start)-1,-1,-1):
        if start[i]<255:
            start[i]+=1
            break
        else:
            start[i]=0
    iprange.append('.'.join(map(str,start)))
return iprange

【讨论】:

    【解决方案3】:

    这个函数返回所有的ip地址,比如从头到尾:

    def ips(start, end):
        import socket, struct
        start = struct.unpack('>I', socket.inet_aton(start))[0]
        end = struct.unpack('>I', socket.inet_aton(end))[0]
        return [socket.inet_ntoa(struct.pack('>I', i)) for i in range(start, end)]
    

    这些是您自己构建它的构建块:

    >>> import socket, struct
    >>> ip = '0.0.0.5'
    >>> i = struct.unpack('>I', socket.inet_aton(ip))[0]
    >>> i
    5
    >>> i += 1
    >>> socket.inet_ntoa(struct.pack('>I', i))
    '0.0.0.6'
    

    例子:

    ips('1.2.3.4', '1.2.4.5')
    ['1.2.3.4', '1.2.3.5', '1.2.3.6', '1.2.3.7', ..., '1.2.3.253', '1.2.3.254', '1.2.3.255', '1.2.4.0', '1.2.4.1', '1.2.4.2', '1.2.4.3', '1.2.4.4']
    

    从文件中读取

    在你的情况下,你可以从这样的文件中读取:

    with open('file') as f:
        for line in f:
            start, end = line.strip().split('-')
            # ....
    

    【讨论】:

    • 为什么这没有被标记为接受的答案? @Leadri 从 python 文件中读取文本是一项基本任务,您可以找到数百个其他帖子,这些帖子可以向您展示如何完成这一任务。原来的问题在这里得到了明确的回答,剩下的你需要努力使用 google/duckduckgo。
    • 这太好了-谢谢。建议 start 和 end 的输入可能是包容性的,在这种情况下,最后一行将是 range(start, end + 1)]
    猜你喜欢
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    • 2022-01-13
    • 2020-01-21
    • 2021-09-14
    相关资源
    最近更新 更多