Python 从非常大的(密码)列表中聚合和删除重复项的有效方法
背景:Python 从非常大的(密码)列表中聚合和删除重复项的有效方法,python,sql,sqlite,passwords,large-files,Python,Sql,Sqlite,Passwords,Large Files,背景: 我试图将大量单独的密码列表文本文件合并到一个文件中,以用于基于字典的密码破解 每个文本文件以行分隔(每行一个密码),目前有82个单独的文件。大多数(66个)文件大小在1-100Mb之间,12个文件大小在100-700Mb之间,3个文件大小在2Gb之间,1个(问题最多)文件大小在11.2Gb之间 我估计总共有17.5亿个非唯一密码需要处理;我估计其中约4.5亿(%25)将是重复的,最终需要丢弃 我正试图在一个有超过6Gb的可用RAM(即8Gb,2Gb已经消耗)的设备上执行此操作 问题:
- 我试图将大量单独的密码列表文本文件合并到一个文件中,以用于基于字典的密码破解
- 每个文本文件以行分隔(每行一个密码),目前有82个单独的文件。大多数(66个)文件大小在1-100Mb之间,12个文件大小在100-700Mb之间,3个文件大小在2Gb之间,1个(问题最多)文件大小在11.2Gb之间
- 我估计总共有17.5亿个非唯一密码需要处理;我估计其中约4.5亿(%25)将是重复的,最终需要丢弃
- 我正试图在一个有超过6Gb的可用RAM(即8Gb,2Gb已经消耗)的设备上执行此操作
我今天在这里的请求是为编程和优化方法提供建议/解决方案,以了解如何实现我庞大、独特的密码列表(最好使用Python)。如果我已经偏离了目标,我完全愿意采取完全不同的策略
两个很好的选择是:
- 一种在将来添加更多密码而不必重新生成整个列表的方法;及
- 这一切结束时,数据库的容量小于20Gb,这样移动起来就不会太痛苦
解决方案 基于CL的解决方案,最终比我想象的要优雅得多,我提出了一个稍微修改的方法 根据CL的建议,我设置了一个sqlite3db,并将文本文件输入到一个Python脚本中,该脚本使用它们,然后输出一个命令将它们插入DB。这个~确实~起了作用,但速度非常(不可能)慢 我通过一些简单的DB优化解决了这个问题,这些优化更容易实现,而且更干净,只需从下面包含的核心Python脚本中执行,该脚本构建于CL的框架代码之上。原始代码正在生成soooooooo许多I/O操作,这一事实在我的(Win7)操作系统上引起了一些有趣的事情,导致BSOD和数据丢失。我通过将整个密码文件插入一个SQL事务加上几个pragma更改来解决这个问题。最后,代码以每秒30000次的速度运行,这不是最好的,但对于我的目的来说是可以接受的 可能在最大的文件上仍然会失败,但如果是这样,我将把文件分成更小的1Gb部分,并单独使用它们
import sys
import apsw
i = 0
con = apsw.Connection("passwords_test.db")
cur = con.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS Passwords(password TEXT PRIMARY KEY) WITHOUT ROWID;")
cur.execute("PRAGMA journal_mode = MEMORY;")
cur.execute("PRAGMA synchronous = OFF;")
cur.execute("BEGIN TRANSACTION")
for line in sys.stdin:
escaped = line.rstrip().replace("'", "''")
cur.execute("INSERT OR IGNORE INTO Passwords VALUES(?);", (escaped,))
i += 1
if i % 100000 == 0: # Simple line counter to show how far through a file we are
print i
cur.execute("COMMIT")
con.close(True)
然后从命令行运行此代码:
insert_passwords.py < passwordfile1.txt
insert_passwords.py
并通过以下方式实现自动化:
for %%f in (*.txt) do (
insert_passwords.py < %%f
)
(*.txt)中%%f的(
插入_passwords.py<%%f
)
总而言之,DB文件本身没有增长太快,插入率足够,我可以立即中断/恢复操作,重复值被准确地丢弃,当前的限制因素是DB的查找速度,而不是CPU或磁盘空间。在SQL数据库中存储密码时,能够检测重复项需要索引。 这意味着密码存储两次,一次存储在表中,一次存储在索引中 但是,SQLite或更高版本支持(在其他数据库中称为“聚集索引”或“索引组织表”),这避免了主键的单独索引 没有包含SQLite 3.8.2的Python版本。 如果不使用,仍然可以使用Python创建SQL命令:
sqlite3
命令行shell()$ sqlite3 passwords.db
SQLite version 3.8.5 2014-06-02 21:00:34
Enter ".help" for usage hints.
sqlite> CREATE TABLE MyTable(password TEXT PRIMARY KEY) WITHOUT ROWID;
sqlite> .exit
import sys
print "BEGIN;"
for line in sys.stdin:
escaped = line.rstrip().replace("'", "''")
print "INSERT OR IGNORE INTO MyTable VALUES('%s');" % escaped
print "COMMIT;"
(如果重复项违反主键的唯一约束,INSERT或IGNORE语句将不会插入行。)$ python insert_passwords.py < passwords.txt | sqlite3 passwords.db
$python insert_passwords.py
不需要拆分输入文件;事务越少,开销就越小。你能告诉我密码是以什么格式保存在文件中的吗?就像你把密码保存到数据库中一样。只需将密码文本字段设置为唯一。然后编写一个python脚本逐行遍历文件,并将它们插入数据库。然后建造