2

我正在尝试从 Enom API 调用构建域名列表。我得到了很多信息,需要找到域名相关的线路,然后将它们连接在一起。

从 Enom 返回的字符串看起来有点像这样:

SLD1=domain1
TLD1=com
SLD2=domain2
TLD2=org
TLDOverride=1
SLD3=domain3
TLD4=co.uk
SLD5=domain4
TLD5=net
TLDOverride=1

我想建立一个看起来像这样的列表:

[domain1.com, domain2.org, domain3.co.uk, domain4.net]

为了找到不同的域名组件,我尝试了以下方法(其中“enom”是上面的字符串),但只能获得 SLD 和 TLD 匹配项。

re.findall("^.*(SLD|TLD).*$", enom, re.M) 
4

9 回答 9

6

编辑: 每次我看到一个要求正则表达式解决方案的问题时,我都有一种奇怪的冲动,即尝试在没有正则表达式的情况下解决它。大多数时候它比使用正则表达式更有效,我鼓励 OP 测试哪种解​​决方案最有效。

这是天真的方法:

a = """SLD1=domain1
TLD1=com
SLD2=domain2
TLD2=org
TLDOverride=1
SLD3=domain3
TLD4=co.uk
SLD5=domain4
TLD5=net
TLDOverride=1"""

b = a.split("\n")
c = [x.split("=")[1] for x in b if x != 'TLDOverride=1']
for x in range(0,len(c),2):
    print ".".join(c[x:x+2])

>> domain1.com
>> domain2.org
>> domain3.co.uk
>> domain4.net
于 2013-05-26T12:23:23.577 回答
4

您的表达式中有一个捕获组。re.findall文档说:

如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。

这就是为什么只返回捕获组的内容。

尝试:

re.findall("^.*((?:SLD|TLD)\d*)=(.*)$", enom, re.M)

这将返回一个元组列表:

[('SLD1', 'domain1'), ('TLD1', 'com'), ('SLD2', 'domain2'), ('TLD2', 'org'), ('SLD3', 'domain3'), ('TLD4', 'co.uk'), ('SLD5', 'domain4'), ('TLD5', 'net')]

然后结合 SLD 和 TLD 由您决定。

于 2013-05-26T12:23:40.740 回答
3

这适用于你的例子,

>>> sld_list = re.findall("^.*SLD[0-9]*?=(.*?)$", enom, re.M)
>>> tld_list = re.findall("^.*TLD[0-9]*?=(.*?)$", enom, re.M)
>>> map(lambda x: x[0] + '.' + x[1], zip(sld_list, tld_list))
['domain1.com', 'domain2.org', 'domain3.co.uk', 'domain4.net']
于 2013-05-26T12:25:28.983 回答
3

我不确定你为什么在谈论正则表达式。我的意思是,你为什么不直接运行一个for循环?

一句名言在这里似乎很合适:

有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。

domains = []
components = []
for line in enom.split('\n'):
  k,v = line.split('=')
  if k == 'TLDOverride':
    continue
  components.append(v)
  if k.startswith('TLD'):
    domains.append('.'.join(components))
    components = []

PS我不确定这是什么TLDOverride所以代码只是忽略它。

于 2013-05-26T12:25:55.793 回答
2

这是一种方法:

import re
print map('.'.join,  zip(*[iter(re.findall(r'^(?:S|T)LD\d+=(.*)$', text, re.M))]*2))
# ['domain1.com', 'domain2.org', 'domain3.co.uk', 'domain4.net']
于 2013-05-26T12:30:58.523 回答
2

只是为了好玩,地图 -> 过滤器 -> 地图:

input = """
SLD1=domain1
TLD1=com
SLD2=domain2
TLD2=org
TLDOverride=1
SLD3=domain3
TLD4=co.uk
SLD5=domain4
TLD5=net
"""

splited = map(lambda x: x.split("="), input.split())
slds = filter(lambda x: x[1][0].startswith('SLD'), enumerate(splited))
print map(lambda x: '.'.join([x[1][1], splited[x[0] + 1][1], ]), slds)

>>> ['domain1.com', 'domain2.org', 'domain3.co.uk', 'domain4.net']
于 2013-05-26T12:56:36.080 回答
1

正如其他一些答案已经说过的那样,这里不需要使用正则表达式。一个简单的split过滤就可以了:

lines = data.split("\n") #assuming data contains your input string
sld, tld = [[x.split("=")[1] for x in lines if x[:3] == t] for t in ("SLD", "TLD")]
result = [x+y for x, y in zip(sld, tld)]
于 2013-05-26T13:10:06.933 回答
1

这似乎可以满足您的要求:

domains = re.findall('SLD\d+=(.+)', re.sub(r'\nTLD\d+=', '.', enom))

它假定行已排序并且 SLD 始终位于其 TLD 之前。如果情况并非如此,请尝试以下不带正则表达式的稍微冗长的代码:

d = dict(x.split('=') for x in enom.strip().splitlines())

domains = [
    d[key] + '.' + d.get('T' + key[1:], '') 
    for key in d if key.startswith('SLD')
]
于 2013-05-26T12:34:27.390 回答
1

为此,您需要使用多行正则表达式。这与这篇文章类似。

data = """SLD1=domain1
TLD1=com
SLD2=domain2
TLD2=org
TLDOverride=1
SLD3=domain3
TLD4=co.uk
SLD5=domain4
TLD5=net
TLDOverride=1"""

domain_seq = re.compile(r"SLD\d=(\w+)\nTLD\d=(\w+)", re.M)
for item in domain_seq.finditer(data):
    domain, tld = item.group(1), item.group(2)
    print "%s.%s" % (domain,tld)
于 2013-05-26T12:36:53.447 回答