Discord.py:无法弄清楚如何使用 aiohttp 代替此用例的请求

Discord.py: Can't figure out how to use aiohttp in place of requests for this use case

我的原始代码(使用了 requests 库):

sess = requests.session()
req = sess.get(i) #i is a url
soup = BeautifulSoup(req.content, 'html.parser')
link = soup.find('a')['href']
with sess.get(link, stream=True) as req2:
    with open(os.path.join('C:\save\location', "download.txt"), "wb") as x_file:
        shutil.copyfileobj(req2.raw, x_file)

此代码的作用:

  1. 给我获取位于 url i
  2. 的页面
  3. 使用 bs4.
  4. 在所述页面(它的文本文件)上找到特定的下载 link link
  5. 该网站使用会话 cookie,因此我使用 requests 中的 sessions 将我的 cookie 从一个请求保存到下一个请求,以便它可以下载文件。
  6. 使用 shutil.
  7. 将文本文件写入我的设备中提到的目录

就代码的工作而言,还可以。文件已下载,我在所需文件夹中有名为 download.txt 的所需文件。

但是,当我尝试在 async 函数中将其用作 discord.py 机器人的一部分时,问题就出现了。代码还是做了它该做的事情但是:当它得到多个命令时,它一个接一个地执行,这显然是不可取的。我从 Stack Overflow 本身发现,这是因为在 async 函数中使用 requests 会导致整个代码阻塞,从而导致我观察到的情况。因此,我尝试使用 aiohttp 而不是 requests,这显然适用于 async 函数。我已经设法用 aiohttp 替换了我对 requests 的大部分用法,它似乎运行良好,但是我似乎无法找出正确的语法来完成我在上面所做的事情(下载使用会话 cookie 时的文本文件,bs4shutil.

在使用 aiohttp 时,我将如何保存我的会话 cookie,使用 bs4 并将文件写入我的设备?

编辑 原始 link 和文件是个人性质的,但如果你想要一个样本来测试,这应该以类似的方式工作:

import requests
from bs4 import BeautifulSoup
import os
import shutil

sess = requests.session()
req = sess.get('https://www.gutenberg.org/ebooks/2600')
soup = BeautifulSoup(req.content, 'html.parser')
link = soup.find('a', text="EPUB (no images)")['href']
link="https://www.gutenberg.org"+link
with sess.get(link, stream=True) as req2:
    with open(os.path.join('C:\save\location', "war.epub"), "wb") as x_file:
        shutil.copyfileobj(req2.raw, x_file)

这会在您想要的目录中创建一个名为 war.epub 的文件,其中包含从古腾堡计划下载的 War 和 Peace 的 epub 版本。我将如何使用 aiohttp 而不是请求来实现它?

请注意,我已包含 aiofile 以异步写入文件,因为大文件会导致代码阻塞。

import aiohttp
import asyncio
from bs4 import BeautifulSoup
import os
from aiofile import AIOFile

async def write_file():
    sess = aiohttp.ClientSession()
    req = await sess.get('https://www.gutenberg.org/ebooks/2600')

    soup = BeautifulSoup(await req.read(), 'html.parser')
    link = soup.find('a', text='EPUB (no images)')['href']
    link = 'https://www.gutenberg.org' + link

    req2 = await sess.get(link)

    async with AIOFile(os.path.join('C:\save\location', 'war.epub'), 'wb') as x_file:
        await x_file.write(await req2.read())

    await sess.close()


loop = asyncio.get_event_loop()
loop.run_until_complete(write_file())