Python 解析日志之命名元组,一旦访问了每个日志文件的所有行数据,就可以提取所描述的详细访问信息了。下面使用正则表达式来分解每一行,以此构建出namedtuple
对象。
使用如下正则表达式解析CLF文件的每一行。
可以使用这个正则表达式将每一行分解为包含9个独立数据元素的字典。使用[]
和"
来分隔以time
、request
、referrer
以及user_agent
等为参数的复杂字段,可以轻松地将文本转换为NamedTuple
对象。
可以将每个独立访问概括为NamedTuple
的子类,如下所示:
上面竭力确保了
NamedTuple
的字段名与记录中每一部分的(?P<name>)
构造体中的正则表达式组名称相匹配,以便于将解析后的字典转换为元组供后续处理。
下面的access_iter()
函数要求每个文件都表示为基于文件行的迭代器:
函数local_gzip()
的输出是一组序列的序列。外层序列基于各个日志文件。对于每个文件,都有一个嵌套的可迭代行序列。如果某一行匹配给定的模式,那它就是某种文件访问。可以通过match
字典创建Access
命名元组。不匹配的行数据会被静默丢弃。
基本的设计模式是根据解析函数的结果构建不可变对象。在本例中,解析函数是一个正则表达式匹配器。其他类型的解析也适用于这种设计模式。
还有一些替代方法可以做到这一点。例如可以使用map()
函数,如下所示:
上例中的替代函数只包含必要的解析和Access
对象的构造。它会返回一个Access
对象或者None
对象。下面使用该函数将日志文件扁平化为单个Access
对象流。
这展示了将local_gzip()
函数的输出转换为一系列Access
实例的过程。在本例中,我们将access_builder()
函数应用于具有可迭代结构的嵌套迭代器,该结构是通过读取文件集合得到的。函数filter()
从map()
函数的结果中移除了None
对象。
这里重点展示了许多可用于解析文件的函数式方法。