排序和组织DNS记录

时间:2014-10-31 22:01:43

标签: python dns

所以我有一组相当简单的数据,例如: ['test.sh','api.test.sh','blah.api.test.sh','test.com','api.test.com']

我需要转换为分层数据结构,我想用字典做这个:

{ 'name':'test.sh',
  'children': { 'name':'api.test.sh',
                'children': { 'name':'blah.api.test.sh' }
              }
},
{
  'name':'test.com',
  'children': { 'name':'api.test.com' }
}

基本上对于每个高级别的名字,我都可以按照自己的方式工作并执行我需要做的操作。

我的问题更多地与创建一种简单的方法来排序,匹配和转换数据有关。我可以想到几种方法来做到这一点,但我无法想到任何相当优雅的东西。我也是在python中这样做的。

由于

2 个答案:

答案 0 :(得分:1)

我认为这可能就是你要找的东西:

def sort_dns(l):


    to_return = []
    # Get top-level domains: the domains that contain the less amount of dots.
    count_list = [i.count('.') for i in l]
    min_dots = min(count_list)
    top_domains = [i for i in l if i.count('.') == min_dots]
    # Now for each domain, we find it subdomains.
    for domain in top_domains:
        sub_domains = [i for i in l if domain in i and i is not domain]
        #And untill we aren't at the deepest level, we continue looking for sub domains and repeat the structure
        sub_sub_domains = sort_dns(sub_domains) if not len(sub_domains) == 0 else None
        to_return.append({'name' : domain, 'childrens' : sub_sub_domains})

    return to_return

正如你所看到的那样,如果需要的话,这个函数会递归调用自身无限“深入”。

以您的示例为例,结果如下

[
    {
        'name': 'test.sh',
        'childrens': [
            {
                'name': 'api.test.sh', 
                'childrens': [
                    {'name': 'blah.api.test.sh', 'childrens': None}
                ]
            }
         ]
    },
    {
        'name': 'test.com', 
        'childrens': [
            {'name': 'api.test.com', 'childrens': None}
        ]
    }
]

如你所见,处理多个孩子的情况,根本没有孩子。

请注意,如果您不想要'childrens': None,可以将功能更改为:

def sort_dns(l):


    to_return = []
    # Get top-level domains: the domains that contain the less amount of dots.
    count_list = [i.count('.') for i in l]
    min_dots = min(count_list)
    top_domains = [i for i in l if i.count('.') == min_dots]
    # Now for each domain, we find it subdomains.
    for domain in top_domains:
        sub_domains = [i for i in l if domain in i and i is not domain]
        #And untill we aren't at the deepest level, we continue looking for sub domains and repeat the structure
        sub_sub_domains = sort_dns(sub_domains) if not len(sub_domains) == 0 else None
        if sub_sub_domains:
            to_return.append({'name' : domain, 'childrens' : sub_sub_domains})
        else:
            to_return.append({'name' : domain})

    return to_return

请注意,这是Python3代码。

编辑:我读过roippi答案,这也很有效,他的解决方案肯定是最诡异的。这个的优点是它不需要任何进口。但你真的应该认为roippi的答案是最优雅的。

答案 1 :(得分:1)

所以,我认为通过三个步骤正确解决了这个问题:排序格式

首先,排序输入您的输入以将它们排列在逻辑组中。您可以定义快速辅助函数来定义排序键:

def sorter(netloc):
    split = netloc.split('.')
    return (split[::-1], -len(split))

然后使用它:

data = ['test.sh','api.test.sh','blah.api.test.sh','test.com','api.test.com', 'another.com', 'sub.another.com', 'sub.sub.another.com']

#shuffling data, to show that sorting works
import random
random.shuffle(data)

sorted(data, key=sorter)
Out[14]: 
['another.com',
 'sub.another.com',
 'sub.sub.another.com',
 'test.com',
 'api.test.com',
 'test.sh',
 'api.test.sh',
 'blah.api.test.sh']

现在所有内容的顺序正确,请对itertools.groupby blah.com x.y.z.blah.com部分def grouper(netloc): return ''.join(netloc.split('.')[-2:]) #in-place sort, replicating sorted() call above data.sort(key=sorter) from itertools import groupby [list(g) for k,g in groupby(data, grouper)] Out[27]: [['another.com', 'sub.another.com', 'sub.sub.another.com'], ['test.com', 'api.test.com'], ['test.sh', 'api.test.sh', 'blah.api.test.sh']] 部分进行类似的群组操作:

def make_hierarchy(groups):
     from copy import deepcopy
     _groups = deepcopy(groups)
     ret = []
     for li in _groups:
         current = {}
         ret.append(current)
         while li:
             current['name'] = li.pop()
             if li:
                 nxt = {}
                 current['children'] = nxt
                 current = nxt
     return ret

print(json.dumps(make_hierarchy(grouped), indent=2))
[
  {
    "children": {
      "children": {
        "name": "another.com"
      },
      "name": "sub.another.com"
    },
    "name": "sub.sub.another.com"
  },
  {
    "children": {
      "name": "test.com"
    },
    "name": "api.test.com"
  },
  {
    "children": {
      "children": {
        "name": "test.sh"
      },
      "name": "api.test.sh"
    },
    "name": "blah.api.test.sh"
  }
]

最后,您需要格式化这些组到您想要的层次结构中。这是一个快速而肮脏的实现:

sub1.example.com

最后一个实现取决于几个假设,即在给定组中不会有任何等效长度的netlocs,即sub2.example.com和{{1}}永远不会发生。显然你可以根据需要调整实现。