背景
本来楼主在午间休息,突然老大发了一个压缩包过来,让我处理下.db多文件,然后做一下数据清洗,将目标数据摘取出来。楼主还在蒙蔽中,打开压缩包一看,好家伙多个文件夹的.db文件要清洗处理。我是谁,我在那,我要干什么。。。开始干活,要的很急。
思路
- 先看一下.db文件里有什么,准备一下基础数据处理
- 将多个.db文件中数据合并到一起,做统一处理,否则多级目录逐一处理太麻烦
SQLite处理基础文件
部分敏感IP被替换称了127.0.0.1,不影响功能,我需要统计多IP出现的次数,首先楼主就想到了mysql的IP正则,可惜SQLite不支持正则函数,没办法我选择用字符串切割,然后统计出IP出现的次数,好家伙SQLite与Mysql的字符串截取方法也不一致。
select substr(msg,instr(msg,'SrcIP=')+6,instr(msg,' ')-6) as srcIp, count(1) as count from fw_log GROUP BY srcIp
这里用到SQLite的两个函数处理这里不一一讲解,直接给出链接,如果还有别的函数使用也可参考以下链接:SQLite substr() 函数SQLite substr() 函数从一个指定的字符串中根据指定的起始位置和长度提取子字符串并返回。https://www.sjkjc.com/sqlite-ref/substr/
.db多文件合并
以上为多层级文件,每个.db文件中存储的都是日志
合并前需要先了解SQLite的附加数据库操作,以下为脚本需要用到的
附上SQLite表附加链接:SQLite 附加数据库 | 菜鸟教程
# 如果数据库尚未被创建,上面的命令将创建一个数据库,如果数据库已存在,则把数据库文件名称与逻辑数据库 'Alias-Name' 绑定在一起。 ATTACH DATABASE file_name AS database_name;-- 查看所有表
select name from sqlite_master where type = 'table';
-- 查看所有索引
select name from sqlite_master where type = 'index';
-- 查看所有视图
select name from sqlite_master where type = 'view';
接下来直接上脚本了
import sqlite3
import os
def merge_databases(db1, db2):
con3 = sqlite3.connect(db1)
con3.execute("ATTACH DATABASE '" + db2 + "' as dba")
con3.execute("BEGIN")
for row in con3.execute("SELECT * FROM dba.sqlite_master WHERE type='table'"):
# 此处的ignore就是为了忽略重复ID导致的异常
combine = "INSERT OR IGNORE INTO " + row[1] + " SELECT * FROM dba." + row[1]
print(combine)
con3.execute(combine)
con3.commit()
con3.execute("detach database dba")
def read_files(directory):
fname = []
for root, d_names, f_names in os.walk(directory):
for f in f_names:
c_name = os.path.join(root, f)
filename, file_extension = os.path.splitext(c_name)
fname.append(c_name)
return fname
def batch_merge(directory):
db_files = read_files(directory)
print(db_files)
for db_file in db_files:
# 此处test.db为指定写入文件
merge_databases('./test.db', db_file)
if __name__ == '__main__':
batch_merge('D://fw_log')
- 注意 ./test.db为全量写入文件,不能直接新建,需要导入表结构到test.db中,由于有多条数据,主键可能会冲突,需要将test.db文件中初始化的表结构去掉主键约束
附上大佬相关博客