Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从非常大的(密码)列表中聚合和删除重复项的有效方法_Python_Sql_Sqlite_Passwords_Large Files - Fatal编程技术网

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已经消耗)的设备上执行此操作

问题:

我需要一种方法,a)将所有这些密码聚合在一起,b)在我的RAM内存限制内,在合理的时间窗口内(约7天,理想情况下要少得多,但我真的不在乎是否需要花费数周时间,然后我再也不需要运行它)删除完全重复的密码

我是一名称职的Python程序员,因此已经多次尝试过了。我最成功的尝试是使用sqlite3在硬盘上存储经过处理的密码。然而,这意味着在处理实例之间跟踪哪些文件已经完成(我取消并重新启动了几次以进行更改),这是通过对每个完成的文件进行散列并在每次打开新文件时维护/比较这些文件来实现的。但是,对于非常大的文件,任何进度都将丢失

我一次处理大约10亿行(最多)的文本文件,以防止内存耗尽,而长时间没有反馈。我知道,如果我在24小时的运行时间内实现了~4.5Gb的数据库文件大小,那么我可以在大量时间内完全填充数据库,因此我估计如果要运行,最多需要4天左右的时间来完成所有操作,但我不知道是否/如何最有效地读/写它,也不知道如何处理删除重复项的问题(在填充数据库时执行此操作,或在之后执行其他传递…?是否有更快速的方法在数据库配置中查找唯一性,我不知道?)


我今天在这里的请求是为编程和优化方法提供建议/解决方案,以了解如何实现我庞大、独特的密码列表(最好使用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
    
  • 创建Python脚本以创建INSERT语句:

    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脚本逐行遍历文件,并将它们插入数据库。然后建造