提高Python脚本的吞吐量
我正在处理成千上万的域名,这些域名来自一个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 个回答
我建议使用纯Python的库来进行DNS查询,而不是去调用dig
这个命令,因为启动另一个进程会比较耗时间。当然,网上查找任何东西也会花时间,所以gilesc提到的多线程的建议还是适用的。你可以在谷歌上搜索python dns,会找到一些可以开始使用的选项。
大部分时间都花在调用 dig
这个外部程序上,所以如果想提高速度,就需要使用多线程。这样可以让你同时运行多个 dig
的调用。比如可以参考这个链接: Python Subprocess.Popen from a thread。或者,你也可以使用 Twisted( http://twistedmatrix.com/trac/ )。
补充:你说得对,很多内容其实是不必要的。
嗯,可能是名字解析花了你太多时间。如果不算这部分(也就是说,如果 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/ 来了解示例)