1. 程式人生 > >scrapy 自動終止事件迴圈

scrapy 自動終止事件迴圈

from twisted.internet import reactor  # 事件迴圈 相當於selecet作用 監聽是否有連線成功(終止條件,所有的socket物件都被移除。)
from twisted.web.client import getPage  # socket物件(如果下載完成,自動從事件迴圈中移除)
from twisted.internet import defer  # defer.Deferred 特殊的socket物件(不會發請求,目的是不讓事件迴圈結束,可以手動移除。)

# 1、利用getPage建立socket物件
# 2、將socket物件新增到事件迴圈中
# 3、開始事件迴圈(內部發送請求,並接受響應,當所有的socket請求完成後,終止事件迴圈)


_close = None
count = 0


def response(content):  # 回撥函式
    print(content)
    global count
    count += 1
    if count == 3:  # 如果發的三個請求都返回了
        _close.callback(None)  # 手動移除defer.Deferred,讓事件迴圈結束。


# 表示新增到事件迴圈中
@defer.inlineCallbacks#進行非同步處理
def task():
    url = 'http://www.baidu.com'  # 相當於scrapy中的start_url
    d = getPage(bytes(url.encode("utf-8")))  # 建立連線
    d.addCallback(response)  # 添加回調函式#執行回撥函式 類似scrapy 中的callback函式

    url = 'https://www.bilibili.com/'  # 類似於scrapy中yield Request中的url
    d = getPage(bytes(url.encode("utf-8")))
    d.addCallback(response)  # 添加回調函式

    url = "https://www.taobao.com/"
    d = getPage(bytes(url.encode("utf-8")))
    d.addCallback(response)  # 添加回調函式
    global _close
    _close = defer.Deferred()  # 把特殊的socket物件賦值給全域性變數_close
    yield _close


def stop(*args, **kwargs):
    reactor.stop()


spider1 = task()  # 開啟socket
spider2 = task()  # 開啟socket
dd = defer.DeferredList([spider1, spider2])  # 把爬蟲放到列表中監聽
dd.addBoth(stop)  # 如果socket都完成則呼叫事件迴圈結束的函式
reactor.run()  # 開始事件迴圈

注意:addCallback()方法C要大寫

步驟:首先先把task()這個函式放到defer.inlineCallbacks裝飾器進行非同步處理,在task()裡先發請求,執行回撥函式,最後產生出defer.Deferred這種不發請求的特殊socket物件,把task()的返回的物件放入到defer.DeferredList進行監聽,如果當一個socket物件發的所有請求都返回後只剩下defer.Deferred在事件迴圈中,手動把defer.Deferred這個物件移除,defer.DeferredList監聽到事件迴圈為空了,就自動關閉事件迴圈。