歩いたら休め

なんでこんな模様をしているのですか?

【Python】pyppeteerの非同期処理をこんな実装で行おうと思ってるんですが、どう思います?

pyppeteerで非同期でクローリングする実装をしていて、エラー時に自動でbrowserとpageを開き直してリトライ…って考えてたんですが、あまりにリトライ処理が煩雑になるので

  • 毎回処理したい固定長のurlのリストを受け取る
  • レスポンスはrequests-htmlのものが便利だったので流用
  • ブラウザ操作周りの例外が出たらfetchの外で例外処理して全部やり直す
  • HTMLから必要な情報だけをpyppeteerから取得することもできるが、一度メモリに乗せて同期的な世界に返してしまう

って感じに割り切って実装しようと思ってるんですが、どう思いますか?

↓こんな感じのコード

from pyppeteer import launch
import asyncio
from requests_html import HTML


def fetch(urls, *, headless=True):
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(_async_fetch(urls, headless=headless))


async def _async_fetch(urls, *, headless):
    async with Crawler(headless=headless) as c:
        async def _inner(url):
            async with await c.get(url) as page:
                html = page.html
            return html
        return await asyncio.gather(*[_inner(u) for u in urls])


class Crawler(object):
    def __init__(self, *, headless):
        self._headless = headless

    async def __aenter__(self):
        self._browser = await launch(headless=self._headless)
        return self

    async def __aexit__(self, exc_type, exc, tb):
        await self._browser.close()
        return False

    async def get(self, url):
        page = await self._browser.newPage()
        await page.goto(url)
        return PageResponse(self, page, url)


class PageResponse(object):
    def __init__(self, browser, page, url):
        self._crawler = browser
        self._page = page
        self._url = url

    async def __aenter__(self):
        content = await self._page.evaluate('document.body.textContent', force_expr=True)
        self._html = HTML(html=content, url=self._url)
        return self

    async def __aexit__(self, exc_type, exc, tb):
        await self._page.close()
        return False

    @property
    def html(self):
        return self._html
    
    async def screenshot(self, path):
        await self._page.screenshot(path=path)