1. 程式人生 > >TinScrapy-簡化的Scrapy原碼-查看爬蟲的執行流程

TinScrapy-簡化的Scrapy原碼-查看爬蟲的執行流程

函數 ogr AR req self. parse ces 下載 分享圖片

學習了自定義的TinyScrapy框架,整理出以下定註釋的代碼

技術分享圖片
  1 from twisted.web.client import getPage,defer
  2 from twisted.internet import reactor
  3 import queue
  4 
  5 class Response(object):
  6     ‘‘‘
  7     對返回內容進行封裝為UTF8格式
  8     ‘‘‘
  9     def __init__(self,body,request):
 10         self.body=body
 11         self.request=request
12 self.url=request.url 13 14 @property 15 def text(self): 16 return self.body.decode(utf-8) 17 18 class Request(object): 19 ‘‘‘ 20 封裝,請求的URL 與回調函數 21 ‘‘‘ 22 def __init__(self,url,callback): 23 self.url=url 24 self.callback=callback
25 26 class Scheduler(object):#調度器 27 ‘‘‘ 28 任務調度器 29 ‘‘‘ 30 def __init__(self,engine): 31 self.q=queue.Queue()#隊列 32 self.engine=engine 33 def enqueue_request(self,request): 34 self.q.put(request)#加入隊列 35 def next_request(self): 36 try
: 37 req=self.q.get(block=False)#從隊列中取出 38 except Exception as e: 39 req=None 40 return req 41 def size(self): 42 return self.q.qsize()#隊列是的個數 43 44 class ExecutionEngine(object): #爬蟲引擎 45 46 def __init__(self):#構造 47 self._closewait=None #關閉引擎調用 默認為不關閉 48 self.running=True#引擎默認為運行狀態 49 self.start_requests=None #開始爬取任務 50 self.scheduler=Scheduler(self)#調度器 類 構造自己放入調度器,傳回自身 51 self.inprogress =set() #集合 並發數 52 53 def check_empty(self,response):#檢測任務是否為空 54 if not self.running: 55 print(任務終止。。。。) 56 self._closewait.callback(None) 57 58 def _next_request(self):#下一個爬取任務 59 while self.start_requests:#存在爬取任務 60 try: 61 request=next(self.start_requests) 62 except StopIteration:#如果執行出錯 63 self.start_requests=None#任務變為空 64 else: 65 self.scheduler.enqueue_request(request)#放入調度器中 66 print(len(self.inprogress),=>總任務數,self.scheduler.size(),=>調度器中的任務數) 67 while len(self.inprogress)< 5 and self.scheduler.size()>0: #最大並發數為 5 68 request=self.scheduler.next_request()#調度器中任務 調用自身 69 if not request: 70 break 71 self.inprogress.add(request)#加入任務並發 72 d=getPage(bytes(request.url,encoding=utf-8))#開始爬取任務 73 #d.addError=()#任務出錯時執行 74 #d.addCallback=()#任務成功完成時執行 75 d.addBoth(self._handle_downloader_output,request)#下載 任務 #無論是否成功都執行 有返回值 運行_handle 76 d.addBoth(lambda x,req:self.inprogress.remove(req),request)#正在運行的進行移除 77 d.addBoth(lambda x:self._next_request())#執行本身的函數 78 if len(self.inprogress)==0 and self.scheduler.size()==0: 79 self._closewait.callback(None)#執行關閉程序 80 81 def _handle_downloader_output(self,body,request):#任務後的回調函數 82 ‘‘‘ 83 獲取內容,執行回調函數,並且把回調函數中的返回值獲取,並添加到隊列中 84 :param response: 85 :param request: 86 :return: 87 ‘‘‘ 88 import types 89 response=Response(body,request)#進行封裝 90 func=request.callback or self.spider.parse#如果有回返值,func取回返值 否則 等於任務的最開始內容 91 gen=func(response) 92 if isinstance(gen,types.GeneratorType):#是否是生成器對象 93 for req in gen: 94 self.scheduler.enqueue_request(req) 95 96 @defer.inlineCallbacks 97 def start(self): 98 self._closewait=defer.Deferred()#生成一個空任務對象 用於保持程序 99 yield self._closewait 100 101 @defer.inlineCallbacks 102 def open_spider(self,spider,start_requests):#傳入封裝好的Requset ,任務叠代器 103 self.start_requests=start_requests#任務叠代器 104 self.spider=spider#封裝好的Requset (請求的URL 與回調函數) 105 yield None #生成器,斷點緩存 106 reactor.callLater(0,self._next_request)#立刻執行 下一個爬取任務 107 108 class Crawler(object):#爬蟲執行類 109 def __init__(self,spidercls):#傳入任務(ChoutiSpider,等) 110 self.spidercls=spidercls 111 self.spider =None 112 self.engine=None 113 114 @defer.inlineCallbacks 115 def crawl(self): 116 self.engine=ExecutionEngine()#類實例化 引擎 117 self.spider=self.spidercls()#實例化任務 118 start_requests =iter(self.spider.start_requests())#叠代器 119 yield self.engine.open_spider(self.spider,start_requests)#引擎啟動 120 yield self.engine.start()#開始執行 121 122 class CrawlerProcess(object):#爬蟲任務器 類 123 def __init__(self): 124 self._active=set()#已經執行任務集合 125 self.crawlers=set()# 爬蟲任務集合 126 127 def crawl(self,spidercls,*args,**kwargs):#傳入爬蟲任務 128 crawler=Crawler(spidercls)#爬蟲任務開始 實例化 129 self.crawlers.add(crawler)#爬蟲任務集合 130 d=crawler.crawl(*args,**kwargs)#爬取任務實例化 運行 131 self._active.add(d)#加入已經執行任務集合 132 return d 133 134 def start(self): 135 d1=defer.DeferredList(self._active)#實例化執行對象 136 d1.addBoth(self._stop_reactor)#所有任務結束 調用 stop方法 137 reactor.run() 138 139 def _stop_reactor(self,_=None):#任務停止 140 reactor.stop() 141 142 class Spider(object): 143 def start_requests(self): 144 for url in self.start_urls: 145 yield Request(url,self.parse)#生成器,對URL與回調函數進行封裝 146 147 #=========具體爬蟲任務=======start==========# 148 class ChoutiSpider(Spider):# 149 name=chouti 150 start_urls=[http://dig.chouti.com/,] 151 def parse(self,response): 152 print(response.text) 153 154 class CnblogsSpider(Spider): 155 name=cnblogs 156 start_urls=[http://www.cnblogs.com/,] 157 def parse(self,response): 158 print(response.text) 159 #=========具體爬蟲任務=======end==========# 160 161 if __name__==__main__: 162 spider_cls_list=[ChoutiSpider,CnblogsSpider]#加入任務列表 163 crawler_process=CrawlerProcess()#實例化爬蟲任務器 164 for spider_cls in spider_cls_list: 165 crawler_process.crawl(spider_cls)#傳入任務 166 crawler_process.start()#開始執行
TinyScrapy

TinScrapy-簡化的Scrapy原碼-查看爬蟲的執行流程