作者:admin,发布日期:2020-10-04
阅读:2583;评论:0

应该是今年的第N次更新,由于前段时间比较忙,没有怎么管理博客,最近国庆才有空更新。

写在开头

这篇文章中,我们将使用python的requests包以及内置的reduce等函数,对爱快路由中的网址浏览记录进行批量抓取并做简单分析,主要是为了练手和复习python内置的map和reduce函数。

爱快里面的操作

要获取到网址浏览记录,我们首先需要在爱快中打开此设置,然后爱快才会记录网址浏览记录。

Snipaste_2020-10-04_16-27-05.png

数据的获取

博主首先尝试了爱快自带的导出功能,但是发现自带的导出功能有很大的缺陷,点击批量下载不是直接导出一个文件,而是一个文件一个文件单独下载下来,而且这个记录是按照小时生成的,一个小时会生成一次,这就导致最终导出的文件数量非常多。

Snipaste_2020-10-04_16-08-18.png

经过分析,爱快导出网址浏览记录时,会访问下载链接进行下载,这个下载链接需要鉴权,类似于下面的网址:

http://0.0.0.0/audit_url/20200915T010000

最后的20200915T010000实际为导出文件页面显示的文件名称,而这个文件名称是可以生成的,他的规则看一眼就可得知:

年份+月份+日期+T+时间+0000

而且除了年份为4位外,其他均为2位,不足2位前面补0,所以我们就可以得到文件名的格式

name_format = "2020%02d%02dT%02d0000" # %02d表示2位整数,不足2位左边补0

而在前面提到,这个网址需要鉴权,由于我们不需要整个过程自动化,所以我们直接从谷歌浏览器中登录获取爱快后台的session key,这里只需要用到sess_key这个cookies,剩下据我猜测应该是用于后台js显示:

Snipaste_2020-10-04_16-15-20.png

知道这些后,我们就可以使用requests模块批量进行下载数据了,在这里使用了requests.session(),让requests去管理此次会话

import requests


def main():
    session = requests.session()
    session.cookies["sess_key"] = "" # 前面得到的sess_key
    name_format = "2020%02d%02dT%02d0000"
    for i in range(1, 31): # 生成月份1-30
        for j in range(24): # 生成小时0-23
            name = name_format % (10, i, j)
            data = session.get("http://0.0.0.0/audit_url/%s" % name) # 下载记录
            if data.status_code == 200: # 如果文件存在就写入到本地
                with open("./log/%s" % name, "wb") as f:
                    f.write(data.content)
            print("[+] Download %s" % name) # 输出记录


if __name__ == '__main__':
    main()

运行代码,我们就可以得到所有的日志了:

Snipaste_2020-10-04_16-18-01.png

批量读取日志文件

首先使用os.getcwd()获取当前目录,然后使用os.listdir()来列出目录下所有文件和目录。

这里没有做目录的筛选,因为我们的log目录下面只有日志文件,不存在目录,所以不需要做处理。

接着我们将文件按行读取,然后对其进行分割。

file_list = os.listdir(os.getcwd() + "/log")
print(file_list)
log_list = []
for file in file_list:
    with open("./log/%s" % file, "r") as f:
        for log in f.readlines():
            log_list.append(log.split())

分割后的数据类似于此结构:

[['192.168.1.24', '00:00:00:00:00:00', '1601796769', '2020-10-04', '15:32:49', '5040005', '/', 'vexrmb.i8mc.cn'],
 ['192.168.1.22', '00:00:00:00:00:00', '1601796771', '2020-10-04', '15:32:51', '2990002', '/cgi-bin/httpconn', '0.0.0.0']]

数据分析

首先我们要知道reduce的函数的用法,这里可以参考廖雪峰的网站上的python教程:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017329367486080

然后就是对数据做分析了,我们使用reduce进行了一次最简单的分析,统计每个网站被访问的次数,然后对其进行排序,访问次数最多的在最前面,并且数据结果:

import os
from functools import reduce


def main():
    file_list = os.listdir(os.getcwd() + "/log")
    # print(file_list)
    log_list = []
    for file in file_list:
        with open("./log/%s" % file, "r") as f:
            for log in f.readlines():
                log_list.append(log.split())

    # print(log_list)
    result = reduce(views_count, log_list, {})
    # 按照value对结果字典进行排序
    result = sorted(result.items(), key=lambda x: x[1], reverse=True)
    # 输出结果
    for k, v in result:
        print(k, v)


# reduce处理过程,b[7]为访问的网址,从上方结构可得
def views_count(a, b):
    """

    :type b: str
    :type a: dict
    """
    if b[7] in a.keys():
        a[b[7]] += 1
    else:
        a[b[7]] = 1

    return a


if __name__ == '__main__':
    main()

输出结果类似于下方结果:

vexrmb.i8mc.cn 143867
api.curseforge.com 72558
servermods.forgesvc.net 63151
files.forgecdn.net 58431
media.forgecdn.net 45738
www.mczhifu.com 43427
mcstats.org 28355
101.91.5.187 16397
bStats.org 12798
api.yumc.pw 10627
.....

写在结尾

python的内置reduce,map,filter等函数可以对数据进行简单的处理,当然,对于大量数据,我们可以将其导入hadoop进行流式计算,以获得实时的数据。博主在此篇文章中仅进行的基础分析,对于此类型的数据,还可以对其访问时间段的等数据进行聚合等操作。