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”列表中的链接正在第二次,第三次和第四次被抓取无论如何。
答案 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_done
与Queue.get
来电应为1:1:
Queue.task_done()¶
表示以前排队的任务已完成。由队列使用 消费者线索。对于每个使用的get() 获取任务,后续调用 task_done()告诉队列那个 任务处理完成。
如果join()当前正在阻止,则当所有项目都有时,它将恢复 已经处理(意思是a 已收到task_done()调用 每个放入()的项目 队列)。
如果调用的次数多于放置项目的次数,则会引发ValueError 队列。
你得到[未被捕获] ValueError
例外吗?看起来可能是这样。