文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
7.3 爬虫节点
爬虫节点(SpiderNode)相对简单,主要包含HTML下载器、HTML解析器和爬虫调度器。执行流程如下:
·爬虫调度器从控制节点中的url_q队列读取URL。
·爬虫调度器调用HTML下载器、HTML解析器获取网页中新的URL和标题摘要。
·爬虫调度器将新的URL和标题摘要传入result_q队列交给控制节点。
7.3.1 HTML下载器
HTML下载器的代码和第6章的一致,只要注意网页编码即可。代码如下:
# 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
7.3.2 HTML解析器
HTML解析器的代码和第6章的一致,详细的网页分析过程可以回顾第6章。代码如下:
# 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
7.3.3 爬虫调度器
爬虫调度器需要用到分布式进程中工作进程的代码,具体内容可以参考第1章的分布式进程章节。爬虫调度器需要先连接上控制节点,然后从url_q队列中获取URL,下载并解析网页,接着将获取的数据交给result_q队列并返回给控制节点,代码如下:
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 127.0.0.1,大家可以在一台机器上测试代码的正确性。当然也可以使用三台VPS服务器,两台运行爬虫节点程序,将IP改为控制节点主机的公网IP,一台运行控制节点程序,进行分布式爬取,这样更贴近真实的爬取环境。图7-3为最终爬取的数据,图7-4为new_urls.txt的内容,图7-5为old_urls.txt的内容,大家可以进行对比测试,这个简单的分布式爬虫还有很大的发挥空间,希望大家发挥自己的聪明才智进一步完善。
图7-3 最终爬取的数据
图7-4 new_urls.txt
图7-5 old_urls.txt
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论