爬虫节点可以理解成我们又很多的快递点,要知道我们的快递并不是直接寄到目的地的,需要一个中转站去分流和暂时的存储,爬虫节点就类似于快递中转站的作用。那么,有没有小伙伴知道爬虫节点具体包括了哪些结构呢?为了方便大家的后续使用,小编在进行结构讲解时还加上了代码的使用,下面我们一起看看吧。
爬虫节点相对简单,主要包含HTML下载器、HTML解析器和爬虫调度器。执行流程如下:
爬虫调度器从控制节点中的url_q队列读取URL
爬虫调度器调用HTML下载器、HTML解析器获取网页中新的URL和标题摘要
最后爬虫调度器将新的URL和标题摘要传入result_q队列交给控制节点
HTML下载器
#coding:utf-8 import requests class HtmlDownloader(object): def download(self,url): if url is None: return None user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers={'User-Agent':user_agent} r = requests.get(url,headers=headers) if r.status_code==200: r.encoding='utf-8' return r.text return None
HTML解析器
#coding:utf-8 import re import urlparse from bs4 import BeautifulSoup class HtmlParser(object): def parser(self,page_url,html_cont): ''' 用于解析网页内容抽取URL和数据 :param page_url: 下载页面的URL :param html_cont: 下载的网页内容 :return:返回URL和数据 ''' if page_url is None or html_cont is None: return soup = BeautifulSoup(html_cont,'html.parser',from_encoding='utf-8') new_urls = self._get_new_urls(page_url,soup) new_data = self._get_new_data(page_url,soup) return new_urls,new_data def _get_new_urls(self,page_url,soup): ''' 抽取新的URL集合 :param page_url: 下载页面的URL :param soup:soup :return: 返回新的URL集合 ''' new_urls = set() #抽取符合要求的a标签 links = soup.find_all('a',href=re.compile(r'/view/\d+\.htm')) for link in links: #提取href属性 new_url = link['href'] #拼接成完整网址 new_full_url = urlparse.urljoin(page_url,new_url) new_urls.add(new_full_url) return new_urls def _get_new_data(self,page_url,soup): ''' 抽取有效数据 :param page_url:下载页面的URL :param soup: :return:返回有效数据 ''' data={} data['url']=page_url title = soup.find('dd',class_='lemmaWgt-lemmaTitle-title').find('h1') data['title']=title.get_text() summary = soup.find('div',class_='lemma-summary') #获取tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回 data['summary']=summary.get_text() return data
爬虫调度器
class SpiderWork(object): def __init__(self): #初始化分布式进程中的工作节点的连接工作 # 实现第一步:使用BaseManager注册获取Queue的方法名称 BaseManager.register('get_task_queue') BaseManager.register('get_result_queue') # 实现第二步:连接到服务器: server_addr = '127.0.0.1' print('Connect to server %s...' % server_addr) # 端口和验证口令注意保持与服务进程设置的完全一致: self.m = BaseManager(address=(server_addr, 8001), authkey='baike') # 从网络连接: self.m.connect() # 实现第三步:获取Queue的对象: self.task = self.m.get_task_queue() self.result = self.m.get_result_queue() #初始化网页下载器和解析器 self.downloader = HtmlDownloader() self.parser = HtmlParser() print 'init finish' def crawl(self): while(True): try: if not self.task.empty(): url = self.task.get() if url =='end': print '控制节点通知爬虫节点停止工作...' #接着通知其它节点停止工作 self.result.put({'new_urls':'end','data':'end'}) return print '爬虫节点正在解析:%s'%url.encode('utf-8') content = self.downloader.download(url) new_urls,data = self.parser.parser(url,content) self.result.put({"new_urls":new_urls,"data":data}) except EOFError,e: print "连接工作节点失败" return except Exception,e: print e print 'Crawl fali ' if __name__=="__main__": spider = SpiderWork() spider.crawl()
需要着重说明的是,爬虫节点是分布式爬虫里的一个重要的难点,大家在学习的时候可以多下一些功夫。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试