2010-11-01 3 views
1

REDIT: пытается избежать просто поместить весь блок кода на форуме и сказал исправить это за меня, но здесь это, просто процесс определения ошибки:Как сравнить элемент в очереди с элементом в наборе?

#! /usr/bin/python2.6 
import threading 
import Queue 
import sys 
import urllib 
import urllib2 
from urlparse import urlparse 
from lxml.html import parse, tostring, fromstring 

THREAD_NUMBER = 1 


class Crawler(threading.Thread): 

def __init__(self, queue, mal_urls, max_depth): 
    self.queue = queue 
    self.mal_list = mal_urls 
    self.crawled_links = [] 
    self.max_depth = max_depth 
    self.count = 0 
    threading.Thread.__init__(self) 

def run(self): 
    while True: 
     if self.count <= self.max_depth: 
      self.crawled = set(self.crawled_links) 
      url = self.queue.get() 
      if url not in self.mal_list: 
       self.count += 1 
       self.crawl(url) 
      else: 
       #self.queue.task_done() 
       print("Malicious Link Found: {0}".format(url)) 
       continue 
     else: 
      self.queue.task_done() 
      break 
    print("\nFinished Crawling! Reached Max Depth!") 
    sys.exit(2) 

def crawl(self, tgt): 
    try: 
     url = urlparse(tgt) 
     self.crawled_links.append(tgt) 
     print("\nCrawling {0}".format(tgt)) 
     request = urllib2.Request(tgt) 
     request.add_header("User-Agent", "Mozilla/5,0") 
     opener = urllib2.build_opener() 
     data = opener.open(request) 

    except: # TODO: write explicit exceptions the URLError, ValueERROR ... 
     return 

    doc = parse(data).getroot() 
    for tag in doc.xpath("//a[@href]"): 
     old = tag.get('href') 
     fixed = urllib.unquote(old) 
     self.queue_links(fixed, url) 


def queue_links(self, link, url): 

    if link.startswith('/'): 
     link = "http://" + url.netloc + link 

    elif link.startswith("#"): 
     return 

    elif not link.startswith("http"): 
     link = "http://" + url.netloc + "/" + link 


    if link not in self.crawled_links: 
     self.queue.put(link) 
     self.queue.task_done() 
    else: 
     return 


def make_mal_list(): 
"""Open various malware and phishing related blacklists and create a list 
of URLS from which to compare to the crawled links 
""" 

hosts1 = "hosts.txt" 
hosts2 = "MH-sitelist.txt" 
hosts3 = "urls.txt" 

mal_list = [] 

with open(hosts1) as first: 
    for line1 in first: 
     link = "http://" + line1.strip() 
     mal_list.append(link) 

with open(hosts2) as second: 
    for line2 in second: 
     link = "http://" + line2.strip() 
     mal_list.append(link) 

with open(hosts3) as third: 
    for line3 in third: 
     link = "http://" + line3.strip() 
     mal_list.append(link) 

return mal_list 

def main(): 
    x = int(sys.argv[2]) 
    queue = Queue.Queue() 

    mal_urls = set(make_mal_list()) 
    for i in xrange(THREAD_NUMBER): 
     cr = Crawler(queue, mal_urls, x) 
     cr.start() 


    queue.put(sys.argv[1]) 

    queue.join() 


if __name__ == '__main__': 
    main() 

Так что я» здесь происходит паутина, которая сначала создает набор из нескольких текстовых файлов, содержащих «вредоносные ссылки». Затем запускается поток, проходящий как набор плохих ссылок, так и sys.argv [1]. Начальный поток, затем вызывает функцию обхода, которая извлекает синтаксис lxml.html из sys.argv [1], а затем после разбора всех ссылок на этой начальной странице помещает их в очередь. Цикл продолжается, причем каждая ссылка, помещенная в очередь, удаляется с помощью self.queue.get(). Соответствующая ссылка затем SUPPOSED сравнивается с набором плохих ссылок. Если ссылка оказалась плохой, цикл должен выводить ее на экран, а затем перейти к следующей ссылке, ЕСЛИ она уже сканировала эту ссылку.

Если это не так, сканируйте его, проанализируйте, поместите ссылки в очередь и т. Д., Увеличивая счетчик каждый раз при обходе ссылки и продолжая до тех пор, пока счетчик не достигнет предела, определенного значением, переданным как sys .argv [2]. Проблема в том, что элементы должны запускать оператор if/else для 'if url not in mal_list', а ссылки, помещенные в список 'crawled_already', проходят сканирование со второго, третьего и четвертого времени во всяком случае.

+0

Как это не сработало? Это кажется совершенно верным. – mikerobi

+1

Если вы неправильно описали свою проблему, очередь здесь совершенно не имеет значения, и у вас возникают проблемы с тестом 'a not in x'. Является ли '' 'пользовательский класс с модифицированными методами' __hash__' или '__eq__'? Если код не в порядке, и вам нужно предоставить лучший пример того, что пошло не так. – katrielalex

+0

Ты меня достал. Вот почему я обратился к стеку за помощью :) X создается функцией, которая открывает несколько файлов txt и добавляет в строки указанные файлы в списке, создает набор из списка и возвращает набор. Я поставил тестовую строку вверху одного из текстовых файлов, а затем запустил код. Часть do_something, на самом деле является функцией веб-паука. Он просто держался прямо на паутине, вместо того, чтобы называть do_something_else. – Stev0

ответ

0

Я не понимаю одну деталь этого кода: очереди помечается как task_done, есть ли новая ссылка найдено в self.queue_links, но не как само собой разумеющееся в self.crawl. Я бы подумал, что этот код будет иметь больше смысла:

def crawl(self, tgt): 
    try: 
     url = urlparse(tgt) 
     self.crawled_links.append(tgt) 
     print("\nCrawling {0}".format(tgt)) 
     request = urllib2.Request(tgt) 
     request.add_header("User-Agent", "Mozilla/5,0") 
     opener = urllib2.build_opener() 
     data = opener.open(request) 
     doc = parse(data).getroot() 
     for tag in doc.xpath("//a[@href]"): 
      old = tag.get('href') 
      fixed = urllib.unquote(old) 
      self.queue_links(fixed, url) 
     self.queue.task_done() 
    except: # TODO: write explicit exceptions the URLError, ValueERROR ... 
     pass 

def queue_links(self, link, url): 
    if not link.startswith("#"): 
     if link.startswith('/'): 
      link = "http://" + url.netloc + link 
     elif not link.startswith("http"): 
      link = "http://" + url.netloc + "/" + link 
     if link not in self.crawled_links: 
      self.queue.put(link) 

Я не могу сказать, однако, что у меня есть полный ответ на ваш вопрос.


спустя: docs для Queue.task_done предположить, что task_done должно быть 1: 1 с Queue.get вызовов:

Queue.task_done()¶

Indicate that a formerly enqueued task is complete. Used by queue consumer threads. For each get() used to fetch a task, a subsequent call to task_done() tells the queue that the processing on the task is complete.

If a join() is currently blocking, it will resume when all items have been processed (meaning that a task_done() call was received for every item that had been put() into the queue).

Raises a ValueError if called more times than there were items placed in the queue.

Были ли вы получать [неперехваченные] ValueError исключения? Похоже, это может быть так.

Смежные вопросы