使用Asyncio的Run_In_Executor包装Selenium驱动程序(以及其他阻止调用)

时间:2015-05-11 14:54:55

标签: python-3.x

我正在尝试使用Python中的第一个小型刮刀,我想使用asyncio同时获取多个网站。我已经编写了一个与aiohttp一起使用的函数,但是由于aiohttp.request()不执行javascript,因此这对于抓取一些动态网页并不理想。因此,这促使尝试将Selenium与PhantomJS一起用作无头浏览器。

有几段代码演示了如何使用BaseEventLoop.run_in_executor - such as here - 但是文档很稀疏,我的复制和粘贴模式不够强大。

如果有人愿意扩大使用asyncio来包装阻止通话,或解释在这个特定情况下发生了什么,我会很感激!以下是我到目前为止所打击的内容:

@asyncio.coroutine
def fetch_page_pjs(self, url):
    '''
    (self, string, int) -> None
    Performs async website content retrieval
    '''
    loop = asyncio.get_event_loop()
    try:
        future = loop.run_in_executor(None, self.driver.get, url)
        print(url)
        response = yield from future
        print(response)
        if response.status == 200:
            body = BeautifulSoup(self.driver.page_source)
            self.results.append((url, body))
        else:
            self.results.append((url, ''))
    except:
        self.results.append((url, ''))

响应返回'无' - 为什么?

1 个答案:

答案 0 :(得分:4)

这不是asyncio或run_in_executor问题。硒api根本无法以这种方式使用。第一个driver.get没有返回任何东西。请参阅Docs for selenium。其次,无法直接获取带有selenium的状态代码,请参阅this stack overflow question

此代码对我有用:

@asyncio.coroutine
def fetch_page_pjs(self, url):
    '''
    (self, string, int) -> None
    Performs async website content retrieval
    '''
    loop = asyncio.get_event_loop()
    try:
        future = loop.run_in_executor(None, self.driver.get, url)
        print(url)
        yield from future
        body = BeautifulSoup(self.driver.page_source)
        self.results.append((url, body))

    except:
        self.results.append((url, ''))