如何从Python中的IP范围列表中生成随机IP地址?
我尝试使用ipaddress模块创建一个ip地址列表,然后将其随机化。
ipRanges = [
"103.112.2.0/24"
]
network = ipaddress.IPv4Network(random.choice(ipRanges))
ip= random.choice(list(network))这是我目前的密码。它工作了,但它使用了很多RAM,因为它需要以更好的方式存储在列表中?
发布于 2021-12-17 04:27:23
与其生成所有可能的IP并选择一个IP,不如将IP威胁为32位整数,使用网络地址作为固定的最重要比特,并生成随机主机部分。
import ipaddress, random, struct
def random_ip(network):
network = ipaddress.IPv4Network(network)
network_int, = struct.unpack("!I", network.network_address.packed) # make network address into an integer
rand_bits = network.max_prefixlen - network.prefixlen # calculate the needed bits for the host part
rand_host_int = random.randint(0, 2**rand_bits - 1) # generate random host part
ip_address = ipaddress.IPv4Address(network_int + rand_host_int) # combine the parts
return ip_address.exploded这给了你:
>>> for _ in range(4):
print(random_ip("103.112.2.0/24"))
103.112.2.143
103.112.2.120
103.112.2.75
103.112.2.59
>>> for _ in range(4):
print(random_ip("103.112.164.0/22"))
103.112.165.120
103.112.164.219
103.112.165.159
103.112.166.232
>>> for _ in range(4):
print(random_ip("103.112.164.0/255.255.252.0"))
103.112.165.17
103.112.165.210
103.112.167.184
103.112.166.171
>>> for _ in range(4):
print(random_ip("0.0.0.0/0"))
115.231.216.55
252.123.19.92
218.198.69.183
179.73.234.254发布于 2021-12-17 04:15:33
您可以使用网络掩码和来自IPNetwork对象的地址来构造范围内的IP地址:
import ipaddress
import random
# Pick a CIDR block to use
ipRanges = [
"103.112.2.0/24",
"1.0.0.0/8",
]
network = ipaddress.IPv4Network(random.choice(ipRanges))
# Get the netmask and address as a list of bytes
netmask = network.netmask.packed
address = network.network_address.packed
# Operate on each byte of the address
picked = b''
for netmask_byte, address_byte in zip(netmask, address):
# Pick a random value
val = random.randint(0, 255)
# Or in the random bits not in the netmask with the bits in the address in the netmask
picked += bytes([((255 ^ netmask_byte) & random.randint(0, 255)) | address_byte])
# Turn the result into an IP address
picked = ipaddress.IPv4Address(picked)
print(picked)发布于 2021-12-17 05:50:19
我假设您只对IPv4地址感兴趣,因为这就是您在示例中所显示的。如果您也需要执行IPv6地址,答案就会变得更加复杂。
如果您可以将IP地址的范围转换为整数范围,那么进行随机选择就会容易得多。幸运的是,ipaddress使这个简单,即使它不是简单的。
import ipaddress
import struct
def ip_range(addr_spec):
ip = ipaddress.ip_network(addr_spec)
base = struct.unpack('>I', ip.network_address.packed)[0]
mask = struct.unpack('>I', ip.netmask.packed)[0]
extent = 0x100000000 - mask
return range(base, base+extent)因此,现在您可以将列表转换为更容易处理的内容:
ranges = [ip_range(spec) for spec in ipRanges]您可能希望选择每个IP地址的可能性相等,因此您需要制作一个与每个范围的大小相对应的权重表。
weights = [len(r) for r in ranges]从这里开始,这个过程很简单。首先随机选择一个范围,然后在范围内随机选择一个特定的地址。
import random
rng = random.choices(ranges, weights=weights)[0]
ip_int = random.choice(rng)
ip_addr = ipaddress.ip_address(ip_int)这样做效率更高的原因是,从Python3开始,range返回的是range对象,而不是列表。这个对象是超优化的;它只存储传入的参数,而实现接口所需的只是一点简单的数学--没有必要预先计算所有的值并将它们保存在内存中。例如,len(range)大致是(stop - start) // step。range[i]大致是start + i * step。显然,完整的实现比这要复杂一些,但是内存使用和时间复杂度仍然是O(1)。
https://stackoverflow.com/questions/70387792
复制相似问题