2010-06-22 4 views
2

Я обрабатываю список тысяч доменных имен из DNSBL через dig, создавая CSV URL-адресов и IP-адресов. Это очень трудоемкий процесс, который может занять несколько часов. DNSBL обновляется каждые 15 минут. Есть ли способ увеличить пропускную способность в моем скрипте Python, чтобы идти в ногу с обновлениями сервера?Увеличение пропускной способности в скрипте 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 
+1

Показать сценарий или псевдокод сценария. Таким образом, мы можем предложить улучшения. Список тысяч за 15 минут должен быть легко ограничен ограничениями на python. – Kieveli

+0

+1, пожалуйста, покажите нам, что у вас есть. Кстати, если я правильно понял, вполне вероятно, что это разрешение имен, а не сам сценарий, который занимает так много времени. Если это так, вы можете попробовать использовать потоковое решение. – rbp

+0

Добавлено в соответствии с запросом. – Tom

ответ

2

Ну, это, вероятно, разрешение имен, которое заставляет вас так долго. Если вы посчитаете это (то есть, если так или иначе копай вернется очень быстро), Python должен иметь возможность иметь дело с тысячами записей легко.

Тем не менее, вы должны попробовать резьбовой подход. Это (теоретически) разрешает несколько адресов одновременно, а не последовательно. Вы могли бы так же хорошо использовать dig для этого, и это должно быть тривиально изменить мой примерный код ниже для этого, но чтобы сделать интересными вещи (и, надеюсь, больше pythonic), давайте использовать существующий модуль для этого: 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/)

+0

прекрасно работает, но я продолжаю получать эти ошибки: Файл «/home/okim/dnspython/dns/resolver.py», строка 541, в _compute_timeout рейза Тайм-аут Тайм-аут Любые идеи? – Tom

+0

Очевидно, что ваш сервер имен не может разрешить некоторые из имен в течение таймаута по умолчанию (возможно, авторитетный сервер имен не отвечает). Если вы хотите пропустить их, просто измените строку «except resolver.NXDOMAIN:» на «except (resolver.NXDOMAIN, resolver.Timeout):». Если вы хотите по-разному относиться к этим исключениям, просто добавьте новое предложение except, после NXDOMAIN. Кстати, NXDOMAIN захватывает несуществующие домены. – rbp

+0

Кстати, если вы обнаружите, что проблема - ваш сервер имен, вы можете указать один номинально с помощью «resolver.default_resolver.nameservers.insert (0,« 8.8.8.8 »)». Но я просто говорю об этом для полноты, более вероятно, что в тысячах доменных имен некоторые из них просто не отвечают (особенно, поскольку вы упоминаете, что они происходят из черного списка). – rbp

2

Подавляющее большинство времени здесь проводится во внешних вызовах , так, чтобы улучшить эту скорость, вам необходимо распараллелить. Это позволит вам одновременно запускать несколько вызовов на . См. Например: Python Subprocess.Popen from a thread. Или вы можете использовать Twisted (http://twistedmatrix.com/trac/).

EDIT: Вы правы, многое из этого не нужно.

+0

+1 за то, что он обратил внимание на необходимость потоков вызовов. Вы должны поставить это в свой ответ. –

0

Я бы хотел использовать библиотеку pure-Python для выполнения DNS-запросов, а не делегировать , потому что вызов другого процесса может быть относительно трудоемким. (Конечно, поиск чего-либо в Интернете также относительно трудоемкий, так что gilesc сказал о многопоточности по-прежнему применяется). Поиск в Google для python dns даст вам несколько вариантов для начала работы.

+0

Накладные расходы на запуск новых процессов незначительны по сравнению с временем, затраченным на выполнение DNS-запроса. –

+0

Да, но сетевая задержка уже была покрыта ответом gilesc. –

0

Для того, чтобы идти в ногу с обновлениями сервера, требуется выполнить менее 15 минут. Ваш сценарий занимает 15 минут? Если это не займет 15 минут, все готово!

Я бы исследовал кеширование и отличается от предыдущих прогонов, чтобы повысить производительность.

+0

он уже упоминалось это занимает несколько часов –