1. 工作中IP合并问题

1.1. 需求描述

所给数据:

  1. 从表A中获取散的IP列表
事例:A = [...218.10.5.110, 218.10.5.115, 218.10.5.109, 218.10.5.111,  218.10.15.100...]
  1. 从表B中获取散的IP段列表
事例:B = [...(218.10.5.50, 218.10.5.100), (218.10.5.200, 218.10.5.250), (218.10.15.11, 218.10.15.111)...]

需求:

  1. 如果A中IP 不在 B中的IP段内,则进行推荐。
  2. 且如果A中IP是连续的,则进要进行合并后推荐
  3. 如果给一个IP段,判断IP段是否要推荐
  4. 推荐确认后,推荐的IP段与已知IP段融合

1.2. 解决方法:

      首先整个需求虽然分条描述,但不能全部分开去解决:

1.2.1. 步骤1 数据处理:

一个IP如果按 “.” 分割可以分为四段,而在此暂将前三节当做 key,以第四段不同去划分 IP段 现将列表A和B转换为字典,利用字典key唯一的特性,将相同key的合并去重,并排序

# 列表A转换为字典
unit_node_ip = {}
if subdomain_ips:  # subdomain_ips是查库所得数据,所以在此还做了次存在判定
    for data in subdomain_ips:
        head, tail = ip_segment(data)
        if head in unit_node_ip.keys():
            if tail in unit_node_ip[head]:
                pass
            else:
                unit_node_ip[head].append(tail)
        else:
            unit_node_ip[head] = []
            unit_node_ip[head].append(tail)

# 列表B转化为字典
init_format = [list(map(ip_segment, node)) for node in node_ip]  # node_ip 是列表B
second_format = [[m[0][0], (m[0][1], m[1][1])] for m in init_format]
formatData = {}
for dealData in second_format:
   if dealData[0] in formatData:
       formatData[dealData[0]].append(dealData[1])
   else:
       formatData[dealData[0]] = [dealData[1]]


def ip_segment(ip):
    head, tail = ip.split('.')[:-1], ip.split('.')[-1]
    head = '.'.join(head)
    return head, int(tail)

处理之后数据格式应该为:

A : { '218.10.5':[110, 115, 109, 111], ' 218.10.15 ':[100] } B : { '218.10.5':[(50, 100), (200, 250)], '218.10.15',[(11, 111)]}

1.2.2. 步骤2: 判断该IP和IP段是否应该被推荐

一个IP段共有1-255共255个数. 先从255中减去已知IP段中IP数,得到可被推荐IP. 然后处理A列表,筛选出每个IP段可被推荐的IP

1.2.3. 步骤3: 合并被筛选出来的IP

/* 传入参数为[1, 2, 3, 5, 8, 9] */
def merge_ip(deal_list):
    len_ip = len(deal_list)
    ip_start = deal_list[0]
    node_ip = {}
    for index, value in enumerate(deal_list):
        if value >= ip_start:
            for i in range(len_ip - index):
                if value + i == deal_list[index + i]:
                    ip_end = value + i
                    node_ip[ip_start] = ip_end
                else:
                    ip_start = deal_list[index + i]
                    break
    node_ip_list = []
    for k, v in node_ip.items():
        node_ip_list.append((k, v))
    return node_ip_list

  /* 返回样式为 [(1, 3), (5, 5), (8, 9)] */

1.2.4. 步骤4: 如果确认推荐的IP段,则与已知的IP进行融合

def add(self, ip_start, ip_end, unit_id):
    node_ip = self.ses.query(Node.ip_start, Node.ip_end).filter_by(unit_id=unit_id).all()
    # 两次数据格式处理后,数据形式为[['192.168.1',(100, 150)], ['192.168.1', (160, 200)]]
    init_format = [list(map(self.ip_segment, node)) for node in node_ip]
    second_format = [[m[0][0], (m[0][1], m[1][1])] for m in init_format]
    # 将其前3段相同设为字典key,value为列表  数据形式为{'192.168.1': [(100,150),(160,200)]}
    format_data = {}
    for dealData in second_format:
        if dealData[0] in format_data:
            format_data[dealData[0]].append(dealData[1])
        else:
            format_data[dealData[0]] = [dealData[1]]

    data_head, data_tail_start = self.ip_segment(ip_start)
    _, data_tail_end = self.ip_segment(ip_end)

    if data_head in format_data:
        # 使得字典的value按升序排列
        format_data[data_head] = sorted(format_data[data_head], key=lambda x: x[0], reverse=False)
        # 将要被合并的IP段加入列表
        del_list = []
        # 处理传入IP是 起始为(151,159) 已有IP是(100,150) 或 (160,200)
        for index in range(len(format_data[data_head])):
            if format_data[data_head][index][1] == data_tail_start - 1:
                data_tail_start = format_data[data_head][index][0]
            elif format_data[data_head][index][0] == data_tail_end + 1:
                data_tail_end = format_data[data_head][index][1]
        # 将已有IP段中起始值小于传入IP尾值的加入待删列表,再将已有IP段中尾值小于传入IP起始值的从待删列表中删除
        for index in range(len(format_data[data_head])):
            if format_data[data_head][index][0] <= data_tail_end:
                del_list.append(format_data[data_head][index])
        for index in range(len(format_data[data_head])):
            if format_data[data_head][index][1] <= data_tail_start:
                del_list.remove(format_data[data_head][index])
        if del_list:
            data_tail_start = data_tail_start if data_tail_start <= del_list[0][0] else del_list[0][0]
            data_tail_end = data_tail_end if data_tail_end >= del_list[-1][1] else del_list[-1][1]

        for del_node_ip_tail in del_list:
            del_node_ip_start = data_head + '.' + str(del_node_ip_tail[0])
            del_node = self.ses.query(Node).filter_by(ip_start=del_node_ip_start).first()
            self.ses.delete(del_node)
        self.safe_commit()
        add_node_ip_start = data_head + '.' + str(data_tail_start)
        add_node_ip_end = data_head + '.' + str(data_tail_end)
    else:
        add_node_ip_start = data_head + '.' + str(data_tail_start)
        add_node_ip_end = data_head + '.' + str(data_tail_end)
  ...

results matching ""

    No results matching ""

    results matching ""

      No results matching ""