爬虫基本框架(单机版)伪代码,本质是一个多叉树层次遍历算法,图的广度优先搜索:
import Queue #设置初始网页,树根 initial_page = "http://www.badtom.cn" #新建待爬队列,已爬集合 url_queue = Queue.Queue() seen = set() #初始化待爬队列,已爬集合 seen.insert(initial_page) url_queue.put(initial_page) #待爬队列不为空 while(url_queue.size()>0): current_url = url_queue.get() #取出待爬队例中第一个的url store(current_url) #把这个url代表的网页存储好 for next_url in extract_urls(current_url): #提取这个url里链接的其他url if next_url not in seen: #去重 seen.put(next_url) #更新已爬集合 url_queue.put(next_url) #更新待爬队列
爬虫基本框架(分布式)伪代码,主节点负责维护待爬队列和已爬集合,从节点负责处理页面,提取待爬链接:
#主节点master.py #新建待爬队列,去重结构bf distributed_queue = DistributedQueue() bf = BloomFilter() #待爬队列加入初始页面 initial_page = "www.badtom.cn" distributed_queue.put(initial_page) #server用于监听从节点发送的请求,并处理返回 server = RPCServer() server.listen() #server处理request请求 while(true): request = server.request() #接收从节点发送的请求,没有则阻塞 if request.head == 'GET': #从节点请求任务 if distributed_queue.size() > 0: page = distributed_queue.get() #从待爬队列取出列头 request.sendResponse(page) #发送给从节点 bf.put(page) #加入已爬集合 else: send(null) #所有页面都已爬完,停止程序 break elif request.head == 'POST': #从节点发送待爬回执 for next_url in request.urls if next_url not in bf #不在已爬集合里的加入待爬队列 distributed_queue.put(request.url) #从节点slave.py #client用于向主节点发送请求 client = RPCClient() #从主节点获取url任务,直到待爬队列为空程序停止 while((current_url = client.request_from_master('GET')) != null) #处理当前页面 store(current_url) #提取该页面所有链接 to_send = [] for next_url in extract_urls(current_url): to_send.append(next_url) #发送待爬链接给主节点 client.send_to_master('POST',to_send)