【问题标题】:Discord bot in python asynciopython asyncio中的不和谐机器人
【发布时间】:2021-08-18 10:50:09
【问题描述】:

我用python写了一个机器人,机器人功能:显示股票价格,设置价格限制,当达到这个限制时,向discord发送消息。在这个阶段,机器人只能监控一个动作。如何使其异步,以便它可以同时监控多只股票,并且当达到限制时,它会发送特定股票与价格已达到标记的消息不一致。

from bs4 import BeautifulSoup
import discord
from discord.ext import commands
from config import settings


bot = commands.Bot(command_prefix = settings['prefix'], help_command=None)

@bot.event
async def on_message(message):
    await bot.process_commands(message)
    channel = message.channel
    co = '{0.content}'.format(message).split()
    tes=co[0]
    if tes=='price':
        yo=co[1]
        print(yo)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0'
        }

        r = requests.get(
            ('https://finance.yahoo.com/quote/') + yo + ('?p=') + yo + ('.tsrc=fin-srch'),
            headers=headers)
        soup = BeautifulSoup(r.text, 'lxml')
        content = soup.find('div', {"class": 'My(6px) Pos(r) smartphone_Mt(6px)'}).find('span').text
        print(content)
        await channel.send(f'{yo} - {content}')
        return content

    elif tes=='limit':
        p=co[1]
        su=co[2]
        price=float(su)

        while True:
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0'
            }
            r = requests.get(
                ('https://finance.yahoo.com/quote/') + p + ('?p=') + p + ('.tsrc=fin-srch'),
                headers=headers)
            soup = BeautifulSoup(r.text, 'lxml')

            content = soup.find('div', {"class": 'My(6px) Pos(r) smartphone_Mt(6px)'}).find('span').text
            con=float(content)
            if price<=con:
                await channel.send("достиг")
                break
            print(content)

        return content

bot.run(settings['token'])

【问题讨论】:

    标签: python multithreading discord discord.py python-asyncio


    【解决方案1】:

    如何使它们异步

    要使它们异步,请使用库 aiohttp 而不是 requests,遗憾的是,beautifulsoup 没有其他选择,但我们可以使用 run_in_executor 来实现这一点

    你必须做出的改变:

    • 在文件顶部添加import aiohttp(安装 discord.py 时会自动安装 aiohttp)
    • 在定义机器人后添加bot.session = aiohttp.ClientSession()(在bot = commands.Bot... 行之后)
    • 改变
    r = requests.get(
                ('https://finance.yahoo.com/quote/') + yo + ('?p=') + yo + ('.tsrc=fin-srch'),
                headers=headers)
    

    async with bot.session.get(
                    f'https://finance.yahoo.com/quote/{yo}?p={yo}.tsrc=fin-srch',
                    headers=headers
                ) as r:
        # we will also change `r.text` to `await r.text()`
    

    这基本上是使用会话对象,获取网站的原始 html。与请求相同的工作,但 异步

    • 现在
    soup = BeautifulSoup(r.text, 'lxml')
    content = soup.find('div', {"class": 'My(6px) Pos(r) smartphone_Mt(6px)'}).find('span').text
    

    要使其异步,首先将其添加到函数中

    def scrape(html):
        soup = BeautifulSoup(html, 'lxml')
        content = soup.find('div', {"class": 'My(6px) Pos(r) smartphone_Mt(6px)'}).find('span').text
        return content
    

    这只是将 beautifulsoup 代码包装在一个函数中,该函数采用原始 html amd 返回所需的内容。没有其他的 现在在你的on_message,而不是

    content = soup.find('div', {"class": 'My(6px) Pos(r) smartphone_Mt(6px)'}).find('span').text
    

    content = await bot.loop.run_in_executor(None, scrape, await r.text())
    

    这会在 scrape 函数中运行代码并将 await r.text() 传递给它,这是原始 html。然后在函数中,我们获取原始 html,找到我们的数据并返回它。这里我们获取返回值,并将其保存到一个名为 content 的变量中

    【讨论】:

    • 您是否有任何不理解的特定部分或您觉得难以理解的部分?
    • 我编辑了答案以使其更易于理解:)
    猜你喜欢
    • 2021-10-30
    • 2021-05-27
    • 2021-07-15
    • 2021-02-28
    • 2021-03-29
    • 2021-07-11
    • 2021-03-25
    • 2018-08-13
    • 1970-01-01
    相关资源
    最近更新 更多