首先安装netaddr模块:
pip install netaddr
以ip地址对象表示单个IP地址:
import netaddr
ip = netaddr.IPAddress("192.168.1.1")
print(ip.version)
运行结果:
IPNetwork对象用于表示接受CIDR前缀和网络掩码的子网,网络或vlan:
import netaddr
ip = netaddr.IPNetwork("192.168.1.0/24")
print(ip.ip)
print(ip.broadcast)
print(ip.cidr)
print(ip.netmask) # 子网掩码
运行结果:
指定子网掩码来更改前缀长度:
import netaddr
ip = netaddr.IPNetwork("192.168.1.10/24")
ip.netmask = "255.255.0.0"
print(ip.cidr)
运行结果:
切片和索引
import netaddr
ip = netaddr.IPNetwork("192.168.1.1/24")
print(ip)
ip_list = list(ip)
# print(ip_list)
# 索引
print(len(ip_list), ip_list[0], ip_list[1])
print(ip.cidr)
# 切片
print(ip_list[0:10])
运行结果:
掩码转换:
import netaddr
ip = netaddr.iprange_to_cidrs("192.168.1.1", "192.168.1.100")
print(ip)
运行结果:
子网掩码:
知识点补充:
对于IP192.168.1.0/24,其中/24是子网掩码,表示255.255.255.0,子网掩码也是用32位二进制来表示的。其中/24表示前24位全部表示为1,将其转换为255.255.255.0。同理,对于/16,则为255.255.0.0。
示例代码:
from netaddr import IPNetwork
# ip = IPNetwork("192.168.1.0/32") # 1
# ip = IPNetwork("192.168.1.0/24") # 256
ip = IPNetwork("192.168.1.0/16") # 65536
# ip = IPNetwork("192.168.1.0/8") # 此时ip表示的数量较大,计算较慢
print(ip)
ip_list = list(ip)
# print(ip_list)
# 索引
print(len(ip_list), ip_list[0], ip_list[1])
print(ip.cidr)
# 切片
print(ip_list[0:10])
运行结果:
合并IP:
import netaddr
ip_list = [netaddr.IPAddress("1.1.1.1"), netaddr.IPAddress("1.1.1.2")]
print(netaddr.cidr_merge(ip_list))
运行结果:
合并网段:
import netaddr
ip_list = [netaddr.IPNetwork("1.1.3.0/23"), netaddr.IPNetwork("1.1.0.0/22")]
print(netaddr.cidr_merge(ip_list))
运行结果:
IPSet()用法:
创建IP集,创建空集方法,也可以将IP地址和网络指定为字符串。
示例代码:
from netaddr import IPSet, IPAddress, IPNetwork, IPRange
# 创建一个空集合
aa = IPSet()
print(aa)
bb = IPSet(['192.168.1.1'])
print(bb)
cc = IPSet([IPAddress('192.168.1.1')])
print(cc)
# dd = IPSet(IPNetwork('192.168.1.1'))
dd = IPSet([IPNetwork('192.168.1.1')])
print(dd)
ee = IPSet([IPNetwork('1234::/32')])
print(ee)
ff = IPSet([IPNetwork('192.168.1.1/32')])
print(ff)
gg = IPSet(IPRange('10.0.0.0', '10.0.1.31'))
print(gg)
hh = IPSet(IPRange('0.0.0.0', '255.255.255.255'))
print(hh)
运行结果:
为 IP 集成员的所有 IP 地址进行交互
示例代码:
from netaddr import IPSet
for ip in IPSet(['192.0.2.0/28', '::192.0.2.0/124']):
print(ip)
运行结果:
192.0.2.0
192.0.2.1
192.0.2.2
192.0.2.3
192.0.2.4
192.0.2.5
192.0.2.6
192.0.2.7
192.0.2.8
192.0.2.9
192.0.2.10
192.0.2.11
192.0.2.12
192.0.2.13
192.0.2.14
192.0.2.15
::192.0.2.0
::192.0.2.1
::192.0.2.2
::192.0.2.3
::192.0.2.4
::192.0.2.5
::192.0.2.6
::192.0.2.7
::192.0.2.8
::192.0.2.9
::192.0.2.10
::192.0.2.11
::192.0.2.12
::192.0.2.13
::192.0.2.14
::192.0.2.15
Process finished with exit code 0
示例代码:
from netaddr import IPNetwork, IPSet, INET_PTON
ip_list = IPNetwork('192.168.1.1/28', flags=INET_PTON)
print(len(ip_list))
for ip in IPSet(ip_list):
print(ip)
运行结果:
添加和删除集合元素
示例代码:
from netaddr import IPSet, IPRange
aa = IPSet()
aa.add('192.0.2.0')
print(aa)
aa.remove('192.0.2.0') # 当删除的IP不存在时不会报错
print(aa)
aa.add(IPRange('10.0.0.0', '10.0.0.255'))
print(aa)
aa.remove(IPRange('10.0.0.128', '10.10.10.10'))
print(aa)
运行结果:
Set membership
示例代码:
from netaddr import IPSet, IPRange, IPAddress, IPNetwork
# 一个简单的任意 IP 地址范围
iprange = IPRange('192.0.1.255', '192.0.2.16')
# 在这个定义范围内可以存在的 CIDR 网络
print(iprange.cidrs())
print("*" * 100)
# 一个IP集
ipset = IPSet(['192.0.2.0/28'])
# 遍历任意 IP 地址范围内的 IP 地址,看看它们是否在 IP 集中找到
for ip in iprange:
print(ip, ip in ipset)
print("*" * 100)
# 更多奇特的 IPSet
bigone = IPSet(['0.0.0.0/0'])
print(IPAddress("10.0.0.1") in bigone)
print(IPAddress("0.0.0.0") in bigone)
print(IPAddress("255.255.255") in bigone)
print(IPNetwork("10.0.0.0/24") in bigone)
print(IPAddress("::1") in bigone)
print("*" * 100)
smallone = IPSet(["10.0.0.42/32"])
print(IPAddress("10.0.0.42") in smallone)
print(IPAddress("10.0.0.41") in smallone)
print(IPAddress("10.0.0.43") in smallone)
print(IPNetwork("10.0.0.42/32") in smallone)
print(IPNetwork("10.0.0.42/31") in smallone)
运行结果:
[IPNetwork('192.0.1.255/32'), IPNetwork('192.0.2.0/28'), IPNetwork('192.0.2.16/32')]
****************************************************************************************************
192.0.1.255 False
192.0.2.0 True
192.0.2.1 True
192.0.2.2 True
192.0.2.3 True
192.0.2.4 True
192.0.2.5 True
192.0.2.6 True
192.0.2.7 True
192.0.2.8 True
192.0.2.9 True
192.0.2.10 True
192.0.2.11 True
192.0.2.12 True
192.0.2.13 True
192.0.2.14 True
192.0.2.15 True
192.0.2.16 False
****************************************************************************************************
True
True
True
True
False
****************************************************************************************************
True
False
False
True
False
Process finished with exit code 0
联合、交叉和差异
示例代码:
from netaddr import IPSet, IPRange, IPAddress, IPNetwork
# 联合操作的一些示例
aa = IPSet(['192.0.2.0'])
print(aa)
bb = IPSet(['192.0.2.0']) | IPSet(['192.0.2.1'])
print(bb)
cc = IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3'])
print(cc)
dd = IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/30'])
print(dd)
ee = IPSet(['192.0.2.0']) | IPSet(['192.0.2.1']) | IPSet(['192.0.2.3/31'])
print(ee)
ff = IPSet(['192.0.2.0/24']) | IPSet(['192.0.3.0/24']) | IPSet(['192.0.4.0/24'])
print(ff)
运行结果:
示例代码:
from netaddr import IPSet, IPRange, IPAddress, IPNetwork
# 这是一个同时进行的并集、交集和对称差分操作的示例
adj_cidrs = list(IPNetwork('192.0.2.0/24').subnet(28))
print(adj_cidrs)
even_cidrs = adj_cidrs[::2]
print(even_cidrs)
evens = IPSet(even_cidrs)
print(evens)
print(IPSet(['192.0.2.0/24']) & evens)
odds = IPSet(['192.0.2.0/24']) ^ evens
print(odds)
print(evens | odds)
print(evens & odds)
print(evens ^ odds)
运行结果:
超集和子集
示例代码:
from netaddr import IPSet, IPRange, IPAddress, IPNetwork
# IP 集提供了测试一组地址范围是否适合另一组地址范围的能力
s1 = IPSet(['192.0.2.0/24', '192.0.4.0/24'])
print(s1)
s2 = IPSet(['192.0.2.0', '192.0.4.0'])
print(s2)
print(s1.issuperset(s2))
print(s2.issubset(s1))
print(s2.issuperset(s1))
print(s1.issubset(s2))
运行结果:
示例代码:
from netaddr import IPSet, IPRange, IPAddress, IPNetwork
# IP 以IPv4 地址范围示例
ipv4_addr_space = IPSet(['0.0.0.0/0'])
private = IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '239.192.0.0/14'])
reserved = IPSet(['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '240.0.0.0/4'])
unavailable = reserved | private
available = ipv4_addr_space ^ unavailable
print(ipv4_addr_space)
print(private)
print(reserved)
print(unavailable)
print(available)
print("*" * 100)
for cidr in available.iter_cidrs():
print(cidr, cidr[0], cidr[-1])
print("*" * 100)
print(ipv4_addr_space ^ available)
运行结果:
IPSet(['0.0.0.0/0'])
IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '239.192.0.0/14'])
IPSet(['225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '240.0.0.0/4'])
IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '239.192.0.0/14', '240.0.0.0/4'])
IPSet(['0.0.0.0/5', '8.0.0.0/7', '11.0.0.0/8', '12.0.0.0/6', '16.0.0.0/4', '32.0.0.0/3', '64.0.0.0/2', '128.0.0.0/3', '160.0.0.0/5', '168.0.0.0/6', '172.0.0.0/12', '172.32.0.0/11', '172.64.0.0/10', '172.128.0.0/9', '173.0.0.0/8', '174.0.0.0/7', '176.0.0.0/4', '192.0.0.0/23', '192.0.3.0/24', '192.0.4.0/22', '192.0.8.0/21', '192.0.16.0/20', '192.0.32.0/19', '192.0.64.0/18', '192.0.128.0/17', '192.1.0.0/16', '192.2.0.0/15', '192.4.0.0/14', '192.8.0.0/13', '192.16.0.0/12', '192.32.0.0/11', '192.64.0.0/10', '192.128.0.0/11', '192.160.0.0/13', '192.169.0.0/16', '192.170.0.0/15', '192.172.0.0/14', '192.176.0.0/12', '192.192.0.0/10', '193.0.0.0/8', '194.0.0.0/7', '196.0.0.0/6', '200.0.0.0/5', '208.0.0.0/4', '224.0.0.0/8', '232.0.0.0/7', '239.0.0.0/9', '239.128.0.0/10', '239.196.0.0/14', '239.200.0.0/13', '239.208.0.0/12', '239.224.0.0/11'])
****************************************************************************************************
0.0.0.0/5 0.0.0.0 7.255.255.255
8.0.0.0/7 8.0.0.0 9.255.255.255
11.0.0.0/8 11.0.0.0 11.255.255.255
12.0.0.0/6 12.0.0.0 15.255.255.255
16.0.0.0/4 16.0.0.0 31.255.255.255
32.0.0.0/3 32.0.0.0 63.255.255.255
64.0.0.0/2 64.0.0.0 127.255.255.255
128.0.0.0/3 128.0.0.0 159.255.255.255
160.0.0.0/5 160.0.0.0 167.255.255.255
168.0.0.0/6 168.0.0.0 171.255.255.255
172.0.0.0/12 172.0.0.0 172.15.255.255
172.32.0.0/11 172.32.0.0 172.63.255.255
172.64.0.0/10 172.64.0.0 172.127.255.255
172.128.0.0/9 172.128.0.0 172.255.255.255
173.0.0.0/8 173.0.0.0 173.255.255.255
174.0.0.0/7 174.0.0.0 175.255.255.255
176.0.0.0/4 176.0.0.0 191.255.255.255
192.0.0.0/23 192.0.0.0 192.0.1.255
192.0.3.0/24 192.0.3.0 192.0.3.255
192.0.4.0/22 192.0.4.0 192.0.7.255
192.0.8.0/21 192.0.8.0 192.0.15.255
192.0.16.0/20 192.0.16.0 192.0.31.255
192.0.32.0/19 192.0.32.0 192.0.63.255
192.0.64.0/18 192.0.64.0 192.0.127.255
192.0.128.0/17 192.0.128.0 192.0.255.255
192.1.0.0/16 192.1.0.0 192.1.255.255
192.2.0.0/15 192.2.0.0 192.3.255.255
192.4.0.0/14 192.4.0.0 192.7.255.255
192.8.0.0/13 192.8.0.0 192.15.255.255
192.16.0.0/12 192.16.0.0 192.31.255.255
192.32.0.0/11 192.32.0.0 192.63.255.255
192.64.0.0/10 192.64.0.0 192.127.255.255
192.128.0.0/11 192.128.0.0 192.159.255.255
192.160.0.0/13 192.160.0.0 192.167.255.255
192.169.0.0/16 192.169.0.0 192.169.255.255
192.170.0.0/15 192.170.0.0 192.171.255.255
192.172.0.0/14 192.172.0.0 192.175.255.255
192.176.0.0/12 192.176.0.0 192.191.255.255
192.192.0.0/10 192.192.0.0 192.255.255.255
193.0.0.0/8 193.0.0.0 193.255.255.255
194.0.0.0/7 194.0.0.0 195.255.255.255
196.0.0.0/6 196.0.0.0 199.255.255.255
200.0.0.0/5 200.0.0.0 207.255.255.255
208.0.0.0/4 208.0.0.0 223.255.255.255
224.0.0.0/8 224.0.0.0 224.255.255.255
232.0.0.0/7 232.0.0.0 233.255.255.255
239.0.0.0/9 239.0.0.0 239.127.255.255
239.128.0.0/10 239.128.0.0 239.191.255.255
239.196.0.0/14 239.196.0.0 239.199.255.255
239.200.0.0/13 239.200.0.0 239.207.255.255
239.208.0.0/12 239.208.0.0 239.223.255.255
239.224.0.0/11 239.224.0.0 239.255.255.255
****************************************************************************************************
IPSet(['10.0.0.0/8', '172.16.0.0/12', '192.0.2.0/24', '192.168.0.0/16', '225.0.0.0/8', '226.0.0.0/7', '228.0.0.0/6', '234.0.0.0/7', '236.0.0.0/7', '238.0.0.0/8', '239.192.0.0/14', '240.0.0.0/4'])
Process finished with exit code 0
其它:
示例代码:
from netaddr import IPSet
ip_list = ['0.0.0.1/0', '1.0.0.0/0']
aa = IPSet(ip_list)
print(aa)
运行结果:
更多IPSet()用法参考官网:Tutorial 3: Working with IP sets — netaddr 0.8.0 documentation
其它功能:
import netaddr
ip_str = '192.168.1.1/28'
print(ip_str)
ip = netaddr.IPNetwork(ip_str)
print(ip)
# 子网掩码
print(ip.netmask)
# 广播地址
print(ip.broadcast)
# 网络地址
print(ip.network)
# 取反掩码
print(ip.hostmask)
# 同一段IP总数
print(ip.size)
# 修改地址的掩码长度为28
ip.prefixlen = 28
print(ip)
# 将同一网段的ip,再化为掩码长度为30的几个子网段
ips_list = [x for x in ip.subnet(30)]
print(ips_list)
# 获取某一网段的所有主机地址
ips_len = []
for ip in netaddr.IPNetwork(ip_str).iter_hosts():
# print(ip)
ips_len.append(ip)
print(len(ips_len))
运行结果:
IP范围:
import netaddr
def func(ips):
lst = []
if "-" in ips:
first, last = ips.split("-")
lst.append(netaddr.IPRange(first, last, flags=netaddr.INET_PTON))
else:
lst.append(netaddr.IPNetwork(ips, flags=netaddr.INET_PTON))
return lst
ip1 = "192.168.1.1"
ret1 = func(ip1)
print(ret1)
ip2 = "192.168.1.1-192.168.1.10"
ret2 = func(ip2)
print(ret2)
print(ret2[0])
运行结果:
案例分析1
给出一串带有ip的数据,通过处理后得到所有的ip列表。如数据:"10.1.1.3||10.1.1.6||10.1.1.9-10.1.1.15"
示例代码:
import netaddr
txt = "10.1.1.3||10.1.1.6||10.1.1.9-10.1.1.15"
ips = txt.split("||")
# print(ips)
ips_lst = []
for ip in ips:
if "-" not in ip:
ips_lst.append(ip)
else:
ip_2 = ip.split('-')
ip_range = netaddr.IPRange(ip_2[0], ip_2[1])
ip_lst = [str(ip) for ip in ip_range]
ips_lst.extend(ip_lst)
print(ips_lst)
运行结果:
案例分析2
给出一串带有ip的数据,通过处理后得到所有的ip列表。如数据:"10.1.1.3||10.1.1.6||10.1.1.9-10.1.1.15||10.1.2.20||10.1.1.9-10.1.2.15"
示例代码:
import netaddr
txt = "10.1.1.3||10.1.1.6||10.1.1.9-10.1.1.15||10.1.2.20||10.1.1.9-10.1.2.15"
ips = txt.split("||")
# print(ips)
ips_lst = []
for ip in ips:
if "-" not in ip:
ips_lst.append(ip)
else:
ip_2 = ip.split('-')
ip_range = netaddr.IPRange(ip_2[0], ip_2[1])
ip_lst = [str(ip) for ip in ip_range]
ips_lst.extend(ip_lst)
print(ips_lst)
print(len(ips_lst))
运行结果: