匹配文件中的行并在Python上解析它们

时间:2014-07-11 15:12:45

标签: python regex dns

我有不同行的这个文件,我想从每一行(而不是整个行)中只获取一些信息,这里是一个文件样子的样本:

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?

2 个答案:

答案 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