首页 > 解决方案 > 带有 requests-html 和 aysnchronous 'render' 的 Spyder 中的 Python 是一场噩梦

问题描述

起点是 Spyder IDE。

>Spyder IDE (5.1.0)
>
>The Scientific Python Development Environment | Spyder-IDE.org 
>
>Python 3.8.5 64-bit | Qt 5.12.9 | PyQt5 5.12.3 | Linux 5.4.0-81-generic

我想做什么?抓取一个棘手的博客,似乎 blogspot 混淆了很多,但在 Spyder 中,我有时发现我什至无法抓取自己的主页......

import asyncio
from requests_html import AsyncHTMLSession, HTML, HTMLSession
from bs4 import BeautifulSoup as bs
import re
import os, os.path
from pathlib2 import Path
from collections import OrderedDict as Odict
from datetime import datetime, date, timedelta
import pytz
import unicodedata
import sys

# asession = AsyncHTMLSession()
ass = AsyncHTMLSession()
sss = HTMLSession()

url='http://localhost/index.html'

def syncurl(session=None, url=None):
    r = session.get(url)
    return r

async def asyncurl(session=None, url=None):
    r = await session.get(url)
    #if r.status_code == 200:
        #await r.html.arender()
    return r
    
def gurl(ass, url):
    fiz = lambda : asyncurl(ass, url)
    foz = ass.run(fiz)
    return foz

因此,如果我在 Spyder 中运行它然后执行,我会得到预期的“循环已经运行”的废话。

gurl(ass,url)
Traceback (most recent call last):

  File "<ipython-input-2-ebc91fe79d44>", line 1, in <module>
    gurl(ass,url)

  File "/home/user/PycharmProjects/blogscrape/BlogScraping/asynctest.py", line 38, in gurl
    foz = ass.run(fiz)

  File "/opt/anaconda3/lib/python3.8/site-packages/requests_html.py", line 774, in run
    done, _ = self.loop.run_until_complete(asyncio.wait(tasks))

  File "/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 592, in run_until_complete
    self._check_running()

  File "/opt/anaconda3/lib/python3.8/asyncio/base_events.py", line 552, in _check_running
    raise RuntimeError(f'This event loop is already running : {self._thread_id}')

RuntimeError: This event loop is already running : 139750638774080

我不是想在这里重新发明轮子,我相信很多其他人都有这个问题,但到目前为止我还没有看到一个简洁的答案,(除了它是一个 Spyder 错误等)。我只是想让它在 Spyder 中工作,(主要是因为我喜欢和 pandas 一起玩来看看结果)。我想一种方法是将这个东西作为一个独立的脚本运行,将结果保存到一个泡菜中,然后使用 spyder 重新加载数据框并使用它。但是,嘿,为什么有必要呢?

主要问题是 requests-html 不够清晰。对于任何只是试图解决..的原始问题的人来说,这个错误是非常不透明的。

RuntimeError:无法在现有事件循环中使用 HTMLSession。请改用 AsyncHTMLSession。

是的,我试过用谷歌搜索这个问题,但他们总是开始谈论“异步”的东西。我正在阅读“requests-html”帮助,除此之外的任何内容都高于我的工资等级(目前为零)。

所以有什么建议吗?(只有简单的 IC 设计人员可以理解的来自 asyncio 的简单内容)。

标签: pythonpython-requestsspyderdynamic-html

解决方案


谢谢@Daniel,是的,这似乎确实有效,可以解决上面显示的问题。虽然它不是 100% 完美,因为有时我会收到超时错误,我不知道为什么,但我不再收到超时错误。

只是把它放在一个地方..安装后,

pip install nest_asyncio

只需将以下内容添加到 python 代码中。

import nest_asyncio
nest_asyncio.apply()

这足以让代码在 Spyder 中运行(因为这是最初的问题)。

在“asyncurl”的代码中添加额外的睡眠/超时允许脚本运行,尽管速度很慢,所以不要尝试在脚本中运行太多调用。上述函数修改如下。

async def asyncurl(session=None, url=None):
    r = await session.get(url)
    await asyncio.sleep(5.0)
    # if r.status_code == 200:
    await r.html.arender(timeout=20000)
    return r

推荐阅读