从 apache/niginx 用户 ID cookie 中提取日期

Extract date from apache/niginx userid cookie

网络服务器 Apache 和 Nginx 都可以使用 mod_unique_id/userid 模块为访问者提供 uniqid cookie。这样一个 cookie looks like 四个 uint32 值编码为 base64 字符串。第二个字节是发出 cookie 时的时间戳。

我想提取它的日期和时间。

from base64 import b64decode
from datetime import datetime
import shlex, gzip, glob
from struct import unpack

import pandas as pd
import numpy as np


def get_data() -> pd.DataFrame:
    filenames = glob.glob('data/user_cookie/stat-*.gz')
    for filename in filenames:
        print(filename)
        f = gzip.open(filename, 'rt')
        for row in f.readlines():
            parts = shlex.split(row)
            useragent, raw_cookie = parts[9], parts[16]
            if raw_cookie == '-':
                raw_visit_date = parts[3][1:]
                # this is a first visit
                visit_date = datetime.strptime(raw_visit_date,
                                               '%d/%b/%Y:%H:%M:%S')
            else:
                visit_date = datetime.fromtimestamp(unpack('IIII',
                                                           b64decode(raw_cookie))[1])
            print(useragent, visit_date)


if __name__ == '__main__':
    get_data()

这句话我觉得特别"artificial"。如何让所有代码更多"pythonic"更快?

datetime.fromtimestamp(unpack('IIII', b64decode(raw_cookie))[1])

我不知道 "artificial" 和 "pythonic" 的确切含义,但至少在我的机器上,该代码是不正确的。它在某种程度上是不正确的,会给您提供可能不会被注意到的虚假数据。

unpack'IIII' 格式代码没有指定字节顺序,这在我的 (x86) 机器上会导致错误的时间戳。 documentation 表示省略字节顺序将导致它默认为您机器的字节顺序。但在 mod_uid 版本 2 中,cookie 使用网络字节顺序。使用格式代码 !IIII'.

指定网络字节顺序

如果 "pythonic" 你的意思是将它分布在几行而不是打包成一行,那么它看起来是这样的:

binary_cookie = b64decode(raw_cookie)
fields = unpack('!IIII', binary_cookie)
visit_date = datetime.fromtimestamp(fields[1])