如何将队列中的项目与集合中的项目进行比较?

时间:2010-11-01 16:06:04

标签: python queue set

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]。启动的线程然后调用teh crawl函数从sys.argv [1]中检索lxml.html解析,然后解析出该初始页面中的所有链接后,将它们放入队列中。循环继续,使用self.queue.get()删除队列中的每个链接。然后支持相应的链接以与坏链接集进行比较。如果发现链接错误,则循环应该将其输出到屏幕,然后继续到下一个链接,除非它已经抓取了该链接。

如果还不错,请抓取它,解析它,将其链接放入队列等,每次爬行链接时递增计数器,并继续直到计数器达到由作为sys传递的值确定的限制。的argv [2]。问题是,它应该触发“if url not in mal_list”的if / else语句的项目,以及放置在“crawled_already”列表中的链接正在第二次,第三次和第四次被抓取无论如何。

1 个答案:

答案 0 :(得分: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)

但我不能说,我对你的问题有完整的答案。


稍后:Queue.task_done的{​​{3}}建议task_doneQueue.get来电应为1:1:

  

Queue.task_done()¶

     

表示以前排队的任务已完成。由队列使用   消费者线索。对于每个使用的get()   获取任务,后续调用   task_done()告诉队列那个   任务处理完成。

     

如果join()当前正在阻止,则当所有项目都有时,它将恢复   已经处理(意思是a   已收到task_done()调用   每个放入()的项目   队列)。

     

如果调用的次数多于放置项目的次数,则会引发ValueError   队列。

你得到[未被捕获] ValueError例外吗?看起来可能是这样。