2010-11-01 5 views
1

REDIT: essayait d'éviter tout placer le bloc entier de code sur le forum et dire Correctif pour moi, mais ici, il est simplement le processus de détermination de l'erreur:Comment comparer un élément d'une file d'attente à un élément d'un ensemble?

#! /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() 

Alors ce que je Nous avons ici une araignée Web, qui crée d'abord un ensemble constitué des lignes de plusieurs fichiers texte contenant des «liens malveillants». Puis commence un thread, en passant à la fois l'ensemble des mauvais liens, et sys.argv [1]. Le thread démarré appelle la fonction crawl qui extrait une analyse lxml.html de sys.argv [1], puis après avoir analysé tous les liens de cette page initiale, les place dans la file d'attente. La boucle continue, chaque lien placé dans la file d'attente étant supprimé avec self.queue.get(). Le lien correspondant est alors SUPPOSÉ pour être comparé à l'ensemble des mauvais liens. Si le lien trouvé est mauvais, la boucle est censée le sortir à l'écran, puis continuer jusqu'au lien suivant, SAUF s'il a déjà exploré ce lien. S'il n'est pas mauvais, l'analyser, l'analyser, placer ses liens dans la file d'attente, etc., incrémenter un compteur chaque fois qu'un lien est analysé et continuer jusqu'à ce que le compteur atteigne une limite déterminée par la valeur transmise par sys. .argv [2]. Le problème est que les éléments qui déclenchent l'instruction if/else pour 'si l'URL n'est pas dans mal_list' ne le sont pas, et les liens qui ont été placés dans la liste 'crawled_already' sont explorés une 2ème, 3ème et quatrième fois de toute façon.

+0

Comment ça ne marche pas? Cela semble être parfaitement valide. – mikerobi

+1

Sauf si vous avez mal décrit votre problème, la file d'attente ici est complètement hors de propos et vous rencontrez des problèmes avec le test 'a pas dans x'. Est-ce que 'a' est une classe personnalisée avec les méthodes' __hash__' ou '__eq__' modifiées? Si ce n'est pas le cas, vous devrez fournir un meilleur exemple de ce qui ne va pas. – katrielalex

+0

Vous m'avez eu. C'est pourquoi je me suis tourné vers la pile pour obtenir de l'aide :) X est créé par une fonction qui ouvre plusieurs fichiers txt et ajoute sur les lignes de ces fichiers dans une liste, crée un ensemble de la liste, et retourne l'ensemble. J'ai placé la chaîne de test en haut de l'un des fichiers texte, et que couru le code. La partie do_something, est en fait une fonction web spider. Il a juste continué à spidering, au lieu d'appeler do_something_else. – Stev0

Répondre

0

Je ne comprends pas un détail de ce code: la file d'attente est marquée comme task_done s'il y a un nouveau lien qui se trouve dans self.queue_links, mais pas comme une question de cours en self.crawl. Je l'aurais pensé que ce code serait plus logique:

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) 

Je ne peux pas dire, cependant, que j'ai une réponse complète à votre question.


plus tard: le docs pour Queue.task_done suggèrent que task_done devrait être 1: 1 avec Queue.get appels:

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.

Avez-vous obtenir [] uncaught ValueError exceptions? Il semble que cela puisse être ainsi.

Questions connexes