提高Python脚本的吞吐量

2 投票
4 回答
1330 浏览
提问于 2025-04-16 00:16

我正在处理成千上万的域名,这些域名来自一个DNS黑名单(DNSBL),我通过dig工具来获取它们的信息,并生成一个包含网址和IP地址的CSV文件。这个过程非常耗时,可能需要几个小时。我的服务器每十五分钟就会更新一次DNS黑名单。请问有没有办法让我在Python脚本中提高处理速度,以便跟上服务器的更新?

编辑: 按要求提供脚本。

import re
import subprocess as sp

text = open("domainslist", 'r')
text = text.read()
text = re.split("\n+", text)

file = open('final.csv', 'w')

for element in text:
        try:
            ip = sp.Popen(["dig", "+short", url], stdout = sp.PIPE)
            ip = re.split("\n+", ip.stdout.read())
            file.write(url + "," + ip[0] + "\n")
        except:
            pass

4 个回答

0

我建议使用纯Python的库来进行DNS查询,而不是去调用dig这个命令,因为启动另一个进程会比较耗时间。当然,网上查找任何东西也会花时间,所以gilesc提到的多线程的建议还是适用的。你可以在谷歌上搜索python dns,会找到一些可以开始使用的选项。

2

大部分时间都花在调用 dig 这个外部程序上,所以如果想提高速度,就需要使用多线程。这样可以让你同时运行多个 dig 的调用。比如可以参考这个链接: Python Subprocess.Popen from a thread。或者,你也可以使用 Twisted( http://twistedmatrix.com/trac/ )。

补充:你说得对,很多内容其实是不必要的。

2

嗯,可能是名字解析花了你太多时间。如果不算这部分(也就是说,如果 dig 能很快返回结果),Python 应该能轻松处理成千上万的条目。

话说回来,你可以尝试使用线程的方法。这样的话,理论上可以同时解析多个地址,而不是一个接一个地来。你也可以继续使用 dig 来实现这个,但为了让事情更有趣(也希望能更符合 Python 的风格),我们来用一个现成的模块:dnspython

所以,先安装它:

sudo pip install -f http://www.dnspython.org/kits/1.8.0/ dnspython

然后试试下面这样的代码:

import threading
from dns import resolver

class Resolver(threading.Thread):
    def __init__(self, address, result_dict):
        threading.Thread.__init__(self)
        self.address = address
        self.result_dict = result_dict

    def run(self):
        try:
            result = resolver.query(self.address)[0].to_text()
            self.result_dict[self.address] = result
        except resolver.NXDOMAIN:
            pass


def main():
    infile = open("domainlist", "r")
    intext = infile.readlines()
    threads = []
    results = {}
    for address in [address.strip() for address in intext if address.strip()]:
        resolver_thread = Resolver(address, results)
        threads.append(resolver_thread)
        resolver_thread.start()

    for thread in threads:
        thread.join()

    outfile = open('final.csv', 'w')
    outfile.write("\n".join("%s,%s" % (address, ip) for address, ip in results.iteritems()))
    outfile.close()

if __name__ == '__main__':
    main()

如果这样会同时启动太多线程,你可以尝试分批处理,或者使用队列(可以参考这个链接 http://www.ibm.com/developerworks/aix/library/au-threadingpython/ 来了解示例)

撰写回答