我有不同行的这个文件,我想从每一行(而不是整个行)中只获取一些信息,这里是一个文件样子的样本:
18:10:12.960404 IP 132.227.127.62.12017 > 134.157.0.129.53: 28192+ A? safebrowsing-cache.google.com. (47)
18:10:12.961114 IP 134.157.0.129.53 > 132.227.127.62.12017: 28192 12/4/4 CNAME safebrowsing.cache.l.google.com., A 173.194.40.102, A 173.194.40.103, A 173.194.40.104, A 173.194.40.105, A 173.194.40.110, A 173.194.40.96, A 173.194.40.97, A 173.194.40.98, A 173.194.40.99, A 173.194.40.100, A 173.194.40.101 (394)
18:13:46.206371 IP 132.227.127.62.49296 > 134.157.0.129.53: 47153+ PTR? b._dns-sd._udp.upmc.fr. (40)
18:13:46.206871 IP 134.157.0.129.53 > 132.227.127.62.49296: 47153 NXDomain* 0/1/0 (101)
18:28:57.253746 IP 132.227.127.62.54232 > 134.157.0.129.53: 52694+ TXT? time.apple.com. (32)
18:28:57.254647 IP 134.157.0.129.53 > 132.227.127.62.54232: 52694 1/8/8 TXT "ntp minpoll 9 maxpoll 12 iburst" (381)
.......
.......
它实际上是DNS请求的输出,所以从中我想提取这些元素: [timestamp],[srcip],[src prt],[dst ip],[dst prt],[domaine(如果存在)],[相关的ips地址]
在查看网站上的旧主题之后,我发现re.match()是一个非常有用的方法,但是因为当你看到每一行都不同时,我有点迷失,有些帮助会很棒,这是我到目前为止写的代码,这是正确的:
def extractDNS(filename):
objList = []
obj = {}
with open(filename) as fi:
for line in fi:
line = line.lower().strip()
#18:09:29.960404
m = re.match("(\d+):(\d+):(\d+.\d+)",line)
if m:
obj = {} #New object detected
hou = int(m.group(1))
min = int(m.group(2))
sec = float(m.group(3))
obj["time"] = (hou*3600)+(min*60)+sec
objList.append(obj)
#IP 134.157.0.129.53
m=re.match("IP\s+(\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}).(\d+)",bb)
if m:
obj["dnssrcip"] = m.group(1)
obj["dnssrcport"] = m.group(2)
# > 134.157.0.129.53:
m = re.match("\s+>\s+(\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}).(\d+):",line)
if m:
obj["dnsdstip"] = m.group(1)
obj["dnsdstport"] = m.group(2)
tstFile3=open("outputFile","w+")
tstFile3.write("%s\n" %objList)
tstFile3.close()
extractDNS(sys.argv[1])
我知道我必须在此之后制作if else语句,因为它们后面的内容每次都不同,我在3个案例中展示了我在每个dns输出文件中常见的,它们是:
- A?后跟CNAME,确切的域和IP地址,
- PTR?接下来是NXDOmain,意味着域不存在,所以我将忽略这一行,
- TXT?其次是域名,但它只提供单词,所以我会忽略这两个
我只希望请求他们的回复包含IP地址,在这种情况下是A?
答案 0 :(得分:1)
如果您知道前5列始终存在,为什么不直接拆分该行并直接处理它们(使用datetime作为时间戳,并手动解析IP地址/端口)。然后,您可以使用正则表达式仅匹配CNAME记录和您感兴趣的内容。如果您不打算实际使用输出,则无需对不同的可能性进行正则表达式扫描。因此,如果它与CNAME表单不匹配,那么您不关心它将如何处理。至少,这听起来像是什么。
答案 1 :(得分:0)
正如用户632657所述,没有必要关心你,不管怎样,不关心你的路线。只需为该行使用一个正则表达式,如果它不匹配,则忽略该行:
pattern = re.compile( r'(\d{2}):(\d{2}):(\d{2}\.\d+)\s+IP\s+(\d+\.\d+\.\d+\.\d+)\.(\d+)\s+>\s+(\d+\.\d+\.\d+\.\d+)\.(\d+):\s+(\d+).*?CNAME\s+([^,]+),\s+(.*?)\s+\(\d+\)' )
这只会匹配CNAME记录。您只需要在循环外定义一次。然后,在循环中:
try:
hour, minute, seconds, source_ip, source_port, dst_ip, dst_port, domain, records = pattern.match( line ).groups()
except:
continue
records = [ r.split() for r in records.split( ', ' ) ]
这将拉出您在相关变量中询问过的所有字段,并将关联的IP解析为一对(列,IP)列表,我认为这将很有用:P