1 回答
TA贡献1875条经验 获得超3个赞
我正在使用这种方式:
a = {'StartAddress': ['65.14.88.64', '148.77.37.88', '65.14.41.128', '65.14.40.0', '208.252.49.240', '12.9.27.48',
'107.135.41.16', '47.44.167.240'],
'EndAddress': ['65.14.88.95', '148.77.37.95', '65.14.41.135', '65.14.40.255', '208.252.49.247', '12.9.27.63',
'107.135.41.23', '47.44.167.247']}
df1 = pd.DataFrame(data=a)
# Convert range to netaddr cidr format
def rangetocidr(row):
return netaddr.iprange_to_cidrs(row.StartAddress, row.EndAddress)
df1["CIDR"] = df1.apply(rangetocidr, axis=1)
b = {'IP': ['65.13.88.64', '148.65.37.88', '65.14.88.65', '148.77.37.93', '66.15.41.132', '208.252.49.247', '208.252.49.248', '12.9.27.49']}
df2 = pd.DataFrame(data=b)
# Convert ip to netaddr format
def iptonetaddrformat(row):
return netaddr.IPAddress(row.IP)
df2["IP_Format"] = df2.apply(iptonetaddrformat, axis=1)
df2['IN_CIDR'] = False
for i, row in df2.iterrows():
ip = row['IP']
for j, r in df1.iterrows():
subnet = str(r['CIDR'][0])
if ip_in_subnetwork(ip, subnet):
df2.loc[i, 'IN_CIDR'] = '['+ subnet + ']'
print(df2)
输出:
IP IP_Format IN_CIDR
0 65.13.88.64 65.13.88.64 False
1 148.65.37.88 148.65.37.88 False
2 65.14.88.65 65.14.88.65 [65.14.88.64/27]
3 148.77.37.93 148.77.37.93 [148.77.37.88/29]
4 66.15.41.132 66.15.41.132 False
5 208.252.49.247 208.252.49.247 [208.252.49.240/29]
6 208.252.49.248 208.252.49.248 False
7 12.9.27.49 12.9.27.49 [12.9.27.48/28]
这是我调用的函数以了解 IP 是否在子网中:
import netaddr as netaddr
import socket
import binascii
def ip_in_subnetwork(ip_address, subnetwork):
"""
Returns True if the given IP address belongs to the
subnetwork expressed in CIDR notation, otherwise False.
Both parameters are strings.
Both IPv4 addresses/subnetworks (e.g. "192.168.1.1"
and "192.168.1.0/24") and IPv6 addresses/subnetworks (e.g.
"2a02:a448:ddb0::" and "2a02:a448:ddb0::/44") are accepted.
"""
(ip_integer, version1) = ip_to_integer(ip_address)
(ip_lower, ip_upper, version2) = subnetwork_to_ip_range(subnetwork)
if version1 != version2:
raise ValueError("incompatible IP versions")
return (ip_lower <= ip_integer <= ip_upper)
def ip_to_integer(ip_address):
"""
Converts an IP address expressed as a string to its
representation as an integer value and returns a tuple
(ip_integer, version), with version being the IP version
(either 4 or 6).
Both IPv4 addresses (e.g. "192.168.1.1") and IPv6 addresses
(e.g. "2a02:a448:ddb0::") are accepted.
"""
# try parsing the IP address first as IPv4, then as IPv6
for version in (socket.AF_INET, socket.AF_INET6):
try:
ip_hex = socket.inet_pton(version, ip_address)
ip_integer = int(binascii.hexlify(ip_hex), 16)
return (ip_integer, 4 if version == socket.AF_INET else 6)
except:
pass
raise ValueError("invalid IP address")
def subnetwork_to_ip_range(subnetwork):
"""
Returns a tuple (ip_lower, ip_upper, version) containing the
integer values of the lower and upper IP addresses respectively
in a subnetwork expressed in CIDR notation (as a string), with
version being the subnetwork IP version (either 4 or 6).
Both IPv4 subnetworks (e.g. "192.168.1.0/24") and IPv6
subnetworks (e.g. "2a02:a448:ddb0::/44") are accepted.
"""
try:
fragments = subnetwork.split('/')
network_prefix = fragments[0]
netmask_len = int(fragments[1])
# try parsing the subnetwork first as IPv4, then as IPv6
for version in (socket.AF_INET, socket.AF_INET6):
ip_len = 32 if version == socket.AF_INET else 128
try:
suffix_mask = (1 << (ip_len - netmask_len)) - 1
netmask = ((1 << ip_len) - 1) - suffix_mask
ip_hex = socket.inet_pton(version, network_prefix)
ip_lower = int(binascii.hexlify(ip_hex), 16) & netmask
ip_upper = ip_lower + suffix_mask
return (ip_lower,
ip_upper,
4 if version == socket.AF_INET else 6)
except:
pass
except:
pass
raise ValueError("invalid subnetwork")
添加回答
举报