在 ISP 字典中搜索 IP /24 网络

Search IP /24 network in dict of ISPs

我有一个 IP 地址,我想在第三个点之后替换它。例如 IP

156.13.216.251

输出:

156.13.216.0

有了这个输出,我希望能够搜索字典以匹配结果:

IP 列表=

[
'156.13.216.251'
'156.13.216.250'
]

字典:

 {
            "techCountry": "ISP",
            "techCity": "saint-petersburg",
            "techName": "Cahit Eyigunlu",
            "adminState": "pr.",
            "registrantPostalCode": "e16 1ah",
            "telephone": "+443333031000",
            "domain": "156.13.216.0"
}

由于输出匹配,我想将其附加到具有匹配结果的新字典中。

我曾尝试将其拆分为前三个,但它似乎将其全部拆分:

for i in IPList:
    i.split(".",3)[:3]

您可以使用 Regular Expressions 在第三个点 (match pattern) 上拆分它。

regex = \b\d{1,3}\.\d{1,3}\.\d{1,3}\. 

示例:

如果您有 IP 地址 156.13.216.251 那么,正则表达式将找到 156.13.216.

假设您有一个字典列表,您可以遍历 IPListdct_list 中的字典并检查域是否匹配。

out = [dom for dom in IPList for dct in dct_list if '.'.join(dom.split('.')[:3]) in dct['domain']]

您也可以使用字符串内置方法

ip[0: ip.rfind('.')] + ".123"

rfind 方法从字符串末尾查找出现的字符并提供它的索引

Python 有一个名为 ipaddress.

的库

您可以像这样轻松使用它:

import ipaddress

ip_list = [
'156.13.216.251',
'156.13.216.250'
]

isps = [
     {
        "techCountry": "ISP",
        "techCity": "saint-petersburg",
        "techName": "Cahit Eyigunlu",
        "adminState": "pr.",
        "registrantPostalCode": "e16 1ah",
        "telephone": "+443333031000",
        "domain": "156.13.216.0"
    }
]

# First, I suggest to map the networks to ISPs, otherwise it'll be an O(n) operation
# for every IP.
# We add the /24 to signal a network.
network_to_isp = {isp["domain"] + "/24": isp for isp in isps}


ips_not_found = []
ips_to_isps = {}

for ip in ip_list:
    network = ipaddress.IPv4Network((ip, 24), strict=False)
    isp = network_to_isp.get(str(network))
    if isp is None:
        ips_not_found.append(ip)
    else:
        ips_to_isps[ip] = isp

假设我们不知道网络,希望搜索,下面的代码就可以了。

请记住,每个 IPv4 最多可能进行 32 次搜索。因为我们不知道这个IP所在的网络。我们没有办法绕过它。

import ipaddress

ip_list = [
'156.13.216.251',
'156.13.216.250'
]

isps = [
     {
        "techCountry": "ISP",
        "techCity": "saint-petersburg",
        "techName": "Cahit Eyigunlu",
        "adminState": "pr.",
        "registrantPostalCode": "e16 1ah",
        "telephone": "+443333031000",
        "domain": "156.13.216.0"
    }
]

# First, I suggest to map the networks to ISPs, otherwise it'll be an O(n) operation
# for every IP.
# We assume the network is unknown.
network_to_isp = {ipaddress.ip_address(isp["domain"]): isp for isp in isps}

def iter_supernets(address, *, max_mask=None, min_mask=0):
    network = ipaddress.ip_network(address)
    return (network.supernet(new_prefix=mask)
            for mask in range(max_mask or network.prefixlen, min_mask, -1))

ips_to_isps = {}

for ip in ip_list:
    for network in iter_supernets(ip):
        isp = network_to_isp.get(network.network_address)
        if isp:
            ips_to_isps[ip] = isp
            break
    else:
        raise RuntimeError("No ISP found for {}".format(ip))