(4)在scrapy中嵌入pyppeteer(scrapy+asyncio)

常規(guī)pyppeteer中間件

常規(guī)的pyppeteer中間件恨锚,盡管pyppeteer是基于asyncio的異步框架宇驾,但因?yàn)橥ㄟ^同步的方式調(diào)用,無法發(fā)揮其異步框架的優(yōu)勢(shì)猴伶,會(huì)將scrapy阻塞课舍,相當(dāng)于總并發(fā)降至1,參考github項(xiàng)目(https://github.com/Python3WebSpider/ScrapyPyppeteer.git

import websockets
from scrapy.http import HtmlResponse
from logging import getLogger
import asyncio
import pyppeteer
import logging
from concurrent.futures._base import TimeoutError


class PyppeteerMiddleware():
    def render(self, url, **kwargs):
        async def async_render(url, **kwargs):
            try:
                page = await self.browser.newPage()
                response = await page.goto(url, options={'timeout': int(timeout * 1000)})
                content = await page.content()
                
                return content, response.status
            except TimeoutError:
                return None, 500
            finally:
                if not page.isClosed():
                    await page.close()
               
        return content, status
    
    def process_request(self, request, spider):
        if request.meta.get('render') == 'pyppeteer':
            try:
                html, status = self.render(request.url)
                return HtmlResponse(url=request.url, body=html, request=request, encoding='utf-8',
                                    status=status)
            except websockets.exceptions.ConnectionClosed:
                pass
    

異步pyppeteer中間件

將pyppeteer中間件弄成異步需要進(jìn)行兩步操作

  1. 在process_request方法中他挎,將pyppeteer請(qǐng)求函數(shù)協(xié)程異步調(diào)用筝尾,并用Deferred.fromFuture將twisted deffered 改成asyncio的future
from twisted.internet.defer import Deferred
from scrapy.http import HtmlResponse

def as_deferred(f):
    """Transform a Twisted Deffered to an Asyncio Future"""

    return Deferred.fromFuture(asyncio.ensure_future(f))


class PuppeteerMiddleware:
    async def _process_request(self, request, spider):
        """Handle the request using Puppeteer"""

        page = await self.browser.newPage()

        ......

        return HtmlResponse(
            page.url,
            status=response.status,
            headers=response.headers,
            body=body,
            encoding='utf-8',
            request=request
        )

    def process_request(self, request, spider):
        """Check if the Request should be handled by Puppeteer"""

        if request.meta.get('render') == 'pyppeteer':
            return as_deferred(self._process_request(request, spider))
        
        return None

  1. 由于scrapy是基于twisted,而pyppeteer基于asyncio办桨,需要解決reactor的互通問題筹淫。
    Twisted有一個(gè)解決方案,可以在asyncio上運(yùn)行twisted呢撞,那就是asyncioreactor损姜,不過要確保在導(dǎo)入scrappy或執(zhí)行任何其他操作之前做處理饰剥,可以在導(dǎo)入execute之前先解決reactor問題
import asyncio
from twisted.internet import asyncioreactor

asyncioreactor.install(asyncio.get_event_loop())

'''
導(dǎo)入scrapy之前,必須先加上以上三行摧阅,否則無法對(duì)接asyncio
'''

from scrapy.cmdline import execute


execute("scrapy crawl spider_name".split())

參考github項(xiàng)目(https://github.com/clemfromspace/scrapy-puppeteer.git

這樣就可以兼容scrapy的并發(fā)設(shè)置了汰蓉。

參考

  1. https://github.com/Python3WebSpider/ScrapyPyppeteer.git
  2. https://github.com/clemfromspace/scrapy-puppeteer.git
  3. https://medium.com/@yashrsharma44/using-asyncio-in-twisted-5c2457e23618
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市逸尖,隨后出現(xiàn)的幾起案子古沥,更是在濱河造成了極大的恐慌,老刑警劉巖娇跟,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岩齿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苞俘,警方通過查閱死者的電腦和手機(jī)盹沈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吃谣,“玉大人乞封,你說我怎么就攤上這事「诒铮” “怎么了肃晚?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)仔戈。 經(jīng)常有香客問我关串,道長(zhǎng),這世上最難降的妖魔是什么监徘? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任晋修,我火速辦了婚禮,結(jié)果婚禮上凰盔,老公的妹妹穿的比我還像新娘墓卦。我一直安慰自己,他們只是感情好户敬,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布落剪。 她就那樣靜靜地躺著,像睡著了一般尿庐。 火紅的嫁衣襯著肌膚如雪忠怖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天屁倔,我揣著相機(jī)與錄音脑又,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛问麸,可吹牛的內(nèi)容都是我干的往衷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼严卖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼席舍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起哮笆,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤来颤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后稠肘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體福铅,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年项阴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滑黔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡环揽,死狀恐怖略荡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情歉胶,我是刑警寧澤汛兜,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站通今,受9級(jí)特大地震影響粥谬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衡创,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一帝嗡、第九天 我趴在偏房一處隱蔽的房頂上張望晶通。 院中可真熱鬧璃氢,春花似錦、人聲如沸狮辽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喉脖。三九已至椰苟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間树叽,已是汗流浹背舆蝴。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洁仗。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓层皱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親赠潦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叫胖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359