twisted学习笔记
生活随笔
收集整理的這篇文章主要介紹了
twisted学习笔记
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.twisted 的異步基于Deferreds對象
使用twisted 編寫異步代碼時要先導入defer 和reactor
2.用twisted寫一個超簡單的異步爬蟲
import queue from twisted.internet import defer #defer.Deferred(特殊的socket對象),不會發請求 from twisted.internet import reactor #socket對象(如果下載完成... from twisted.web.client import getPage #事件循壞class Request:def __init__(self, url, callback):self.url = urlself.callback = callbackclass HttpResponse:def __init__(self, content, request):self.content = contentself.request = requestself.url = request.urlself.text = str(content.decode('UTF-8'))class XueXiSpider:name = 'xue_xi'def start_request(self):start_url = ['http://www.baidu.com', 'http://www.bing.com', ]for url in start_url:yield Request(url, self.parse)def parse(self, response):print(response.url)yield Request('http://www.cnblogs.com', callback=self.parse)schedule = queue.Queue()class Engine:def __init__(self):# 用來關閉deferred對象self._close = None# 最大并發數self.max = 5# 存放要下載的request用來限制并發數self.crawling = []def get_response_callback(self, content, request):"""調用request的callback函數解析下載的內容并將返回的request對象壓入調度器:param content: 下載內容:param request: request對象:return:"""# 移除下載完的requestself.crawling.remove(request)# 生成response對象response = HttpResponse(content, request)# 調用parse解析responsereqs = request.callback(response)import types# 返回的是生成器對象就迭代它if isinstance(reqs, types.GeneratorType):for req in reqs:# 加入調度器schedule.put(req)def _next_request(self):"""不斷從隊列中獲取request, 當符合條件時關閉deferred對象:return:"""# 判斷是否要關閉deferred, defer.Deferred()對象需要手動關閉if len(self.crawling) == 0 and schedule.qsize() == 0:self._close.callback(None)return# 限制并發, crawling里的request屬相大于5就直接返回, 不在下載if len(self.crawling) > self.max:returnwhile len(self.crawling) < self.max:try:# 從調度器中取出request, block=False以不阻塞的方式req = schedule.get(block=False)# 將要下載的request加入下載列表中self.crawling.append(req)# 調用twisted的getPage 來發起url請求, getPage返回的對象在回調結束后會自動移除d = getPage(req.url.encode('UTF-8'))# 添加解析response回調d.addCallback(self.get_response_callback, req)# 數量不足添加next_request回調繼續獲取request下載d.addCallback(lambda _: reactor.callLater(0, self._next_request))except Exception as e:print(e)return@defer.inlineCallbacksdef crawl(self, spider_):"""將初始request壓入隊列, 定時啟動self._next_request:param spider_: spider對象:return: deferred對象"""# 獲取初始requeststart_requests = iter(spider_.start_request())while True:try:# 加入隊列schedule.put(next(start_requests))except StopIteration:break# 調用crawl函數后不會立刻執行self._next_request, 而是要等到reactor.run()調用后才會執行self._next_request# 0秒后調用self._next_requestreactor.callLater(0, self._next_request)# 創建不會自動結束的defer.Deferred()對象 賦值給self._close, 在隊列和下載列表為空時結束defer.Deferred()對象self._close = defer.Deferred()yield self._closeif __name__ == '__main__':# 創建集合存放deferred對象_active = set()# 生成spider對象spider = XueXiSpider()# 創建引擎engine = Engine()# 調用crawl方法 返回deferred對象d = engine.crawl(spider)_active.add(d)dd = defer.DeferredList(_active)# 添加結束回調, 當self._close.callback(None) 后停止reactordd.addBoth(lambda a: reactor.stop())# 啟動主事件循環reactor.run()# 注意上述代碼中deferred對象未添加addErrorback()錯誤處理函數, 一旦deferred回調函數出錯, 程序不會報錯, 會一直卡在那里# lambda 函數要加入一個參數, 不能不填參數總結
以上是生活随笔為你收集整理的twisted学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网件r8000刷openwrt官方固件_
- 下一篇: Cisco PT 案例二:为路由器配置并