爬虫节点相对简单,主要包含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()
需要着重说明的是,爬虫节点是分布式爬虫里的一个重要的难点,大家在学习的时候可以多下一些功夫。
上一篇:python分布式爬虫中的Redis是什么?怎么用?
下一篇: 没有了
一级建造师二级建造师消防工程师造价工程师土建职称房地产经纪人公路检测工程师建筑八大员注册建筑师二级造价师监理工程师咨询工程师房地产估价师 城乡规划师结构工程师岩土工程师安全工程师设备监理师环境影响评价土地登记代理公路造价师公路监理师化工工程师暖通工程师给排水工程师计量工程师
执业药师执业医师卫生资格考试卫生高级职称护士资格证初级护师主管护师住院医师临床执业医师临床助理医师中医执业医师中医助理医师中西医医师中西医助理口腔执业医师口腔助理医师公共卫生医师公卫助理医师实践技能内科主治医师外科主治医师中医内科主治儿科主治医师妇产科医师西药士/师中药士/师临床检验技师临床医学理论中医理论