signed

QiShunwang

“诚信为本、客户至上”

判断ip是否在特定网段内

2020/8/19 22:35:22   来源:

一个公司的面试题。特此记录下。
后面有时间在说原理。。。

#!/usr/bin/env python
#-*- coding:utf-8 -*-
"""
@author: zhengxianjun
@contact: 1596492090@qq.com
@datetime:2020/8/19 21:25
@software: PyCharm 
"""

import requests
from fake_useragent import UserAgent
from lxml import etree

def is_edu_id(ip: str) -> bool:
    """判断 ip 是否是教育网ip"""
    # 1. 从 http://ipcn.chacuo.net/view/i_CERNET 获取教育网ip列表
    # 这里使用爬取到的ip文本。如果不用,可以直接使用该网站下载的文件直接读取
    url = 'http://ipcn.chacuo.net/down/t_txt=c_CERNET'
    headers = {
        'User-Agent': UserAgent().random
    }
    resp = requests.get(url=url, headers=headers).content.decode('utf8')
    html = etree.HTML(resp)
    ips = html.xpath('/html/body/pre//text()')
    ip_list = ips[0].split('\r\n')
    # 解析ip text 并将ip网段作为key
    # ip_dict = {ip.split('\t')[0].split('.0')[0]:ip.split('\t')[1] for ip in ips[0].split('\r\n') if ip }
    # 直接解析 生成ip列表,并使之整数化,为后面比较ip是否在该网段内
    ips_tuple = [(int(ip.split('\t')[0].split('.')[0])* 256 * 256 * 256+
                int(ip.split('\t')[0].split('.')[1])* 256 * 256+
                int(ip.split('\t')[0].split('.')[2])* 256+
                int(ip.split('\t')[0].split('.')[3]),
                int(ip.split('\t')[1].split('.')[0])* 256 * 256 * 256+
                int(ip.split('\t')[1].split('.')[1])* 256 * 256+
                int(ip.split('\t')[1].split('.')[2])* 256+
                int(ip.split('\t')[1].split('.')[3])
                )
               for ip in ips[0].split('\r\n') if ip]

    # 2. 判断 ip 是否是 教育网 ip
    # 考虑到网段数据不是很多,直接遍历比较
    target = int(ip.split('.')[0])* 256 * 256 * 256+int(ip.split('.')[1])* 256 * 256 + int(ip.split('.')[2])* 256+int(ip.split('.')[3])
    for begin,end in ips_tuple:
        if target >= begin and target <= end:
            return True

    return False


if __name__ == '__main__':
    flag = is_edu_id('59.255.1.2')
    print(flag)