# -*- coding: utf-8 -*- # 2018.11.23 11:07:22 by Tr0y import sqlite3 import time def _get_hour(): ''' 返回上个小时的时间戳 假如现在是 2018.11.21 19:44:02, 那么返回 '1542794400' 即 2018.11.21 18:00:00 的时间戳 返回值: 字符串;上个小时的时间戳 ''' return int( time.mktime( time.strptime( time.strftime("%Y-%m-%d %H"), "%Y-%m-%d %H") ) )-3600 class MySqlite: def __init__(self, dbname, tablename): ''' 初始化 参数: dbname:字符串;数据库名 tablename:字符串;表名 ''' self.dbname = dbname self.tablename = tablename self.conn = sqlite3.connect(self.dbname) self._create() def _create(self): # ''' 若数据库不存在,则创建数据库 ''' query = """create table IF NOT EXISTS {tablename}( url VARCHAR(100), sha VARCHAR(40), repository VARCHAR(100), keyword VARCHAR(100), filename VARCHAR(100), level VARCHAR(5), update_time VARCHAR(10), last_record_time VARCHAR(10), PRIMARY KEY (url, sha) );""".format(tablename=self.tablename) # 不存在才新建 self.conn.execute(query) self.conn.commit() def _select(self, sql): ''' 查询 参数: sql:字符串;查询的语句 返回值: rows:2 维列表;查询的结果 ''' result = self.conn.execute(sql) self.conn.commit() rows = result.fetchall() return rows # [(, ... ,), (, ... ,)] def _insert(self, url, sha, repository, filename, keyword, level, update_time): ''' 插入数据 column 顺序与参数顺序一致 **插入的数据类型均为字符串** 参数: url: 字符串;代码文件的 url sha: 字符串;代码文件的 sha repository: 字符串;代码文件的仓库 filename: 字符串;代码文件的文件名 keyword: 字符串;代码文件命中的关键字 level: 整数; 泄露级别 update_time:字符串;数据库中此记录被更新的时间 ''' data = '''INSERT INTO {tablename}(url, sha, repository, keyword, filename, level, update_time, last_record_time) VALUES('{url}','{sha}','{repository}','{keyword}','{filename}','{level}','{update_time}', '∞'); '''.format( tablename=self.tablename, url=url, sha=sha, repository=repository, keyword=keyword, filename=filename, level=level, update_time=update_time ) self.conn.execute(data) self.conn.commit() def _update(self, url, sha, repository, filename, keyword, level, update_time, last_record_time): ''' 更新数据 参数: url: 字符串;代码文件的 url sha: 字符串;代码文件的 sha repository: 字符串;代码文件的仓库 filename: 字符串;代码文件的文件名 keyword: 字符串;代码文件命中的关键字 level: 整数; 泄露级别 update_time: 字符串;数据库中此记录被更新的时间 last_record_time:字符串;数据库中此记录上一次被更新的时间 ''' data = '''UPDATE {tablename} SET url='{url}', sha='{sha}', repository='{repository}', keyword='{keyword}', filename='{filename}', level='{level}', update_time='{update_time}', last_record_time='{last_record_time}' where url='{url}'; '''.format( tablename=self.tablename, url=url, sha=sha, repository=repository, keyword=keyword, filename=filename, level=level, update_time=update_time, last_record_time=last_record_time ) self.conn.execute(data) self.conn.commit() def Record(self, url, sha, repository, filename, keyword, update_time, negative): ''' 根据数据库情况,判断新数据记录方式 参数: url: 字符串;代码文件的 url sha: 字符串;代码文件的 sha repository: 字符串;代码文件的仓库 filename: 字符串;代码文件的文件名 keyword: 字符串;代码文件命中的关键字 update_time:字符串;数据库中此记录被更新的时间 negative: 布尔值;是否为误报 返回值 level:整数;泄露级别 ''' result = self._select( '''SELECT url, sha, update_time FROM {tablename} where url='{url}'; '''.format( url=url, tablename=self.tablename )) # 查询是否存在此 url 的记录 if result: # 已存在 if result[0][1] != sha: # 文件 sha 发生变化 if negative: level = 1 else: level = 2 # 旧的 update_time 作为新的 last_record_time self._update(url, sha, repository, filename, keyword, level, update_time, result[0][2]) else: level = 0 else: if negative: level = 1 else: level = 3 self._insert(url, sha, repository, filename, keyword, level, update_time) return level def Get_Data(self, keyword, level): ''' 获取上一轮的泄露记录 参数: keyword:字符串;关键字 level:字符串;泄露级别 返回值: result:2 维列表;泄露记录 ''' last_hour_time = _get_hour() result = self._select('''SELECT * FROM {tablename} where keyword='{keyword}' and update_time>='{last_hour_time}' and update_time<'{now_hour_time}' and level='{level}'; '''.format( tablename=self.tablename, keyword=keyword, level=level, last_hour_time=last_hour_time, now_hour_time=last_hour_time+3600 # 加个小于当前小时的限制,防止此轮刚更新就报告 )) for i, r in enumerate(result): result[i] = list(result[i]) # tuple 转 list result[i][-1] = r[-1] if r[-1] == "∞" else time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime( # 时间戳转成可读性的时间 int(r[-1]) ) ) return result