python asyncio 中的 Discord 机器人
Discord bot in python asyncio
我在 python 中写了一个机器人,该机器人的功能是:显示股票价格,设置价格限制,当达到该限制时,向 discord 发送消息。在此阶段,机器人只能监控一个动作。如何让它异步,让它同时监控几只股票,当达到限制时,它发送特定股票到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'])
如何使它们异步
要使它们异步,请为此使用库 aiohttp instead of requests, and sadly there is no alternative for beautifulsoup that is async but we can use 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。与请求相同的工作,但 async
- 现在
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 和 returns 所需的内容。没有其他的
现在在您的 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 函数中的代码并将等待 r.text() 传递给它,这是原始的 html。然后在函数中,我们得到原始 html,找到我们的数据并 return 它。这里我们得到 returned 值并将其保存到名为 content
的变量中
我在 python 中写了一个机器人,该机器人的功能是:显示股票价格,设置价格限制,当达到该限制时,向 discord 发送消息。在此阶段,机器人只能监控一个动作。如何让它异步,让它同时监控几只股票,当达到限制时,它发送特定股票到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'])
如何使它们异步
要使它们异步,请为此使用库 aiohttp instead of requests, and sadly there is no alternative for beautifulsoup that is async but we can use 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。与请求相同的工作,但 async
- 现在
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 和 returns 所需的内容。没有其他的
现在在您的 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 函数中的代码并将等待 r.text() 传递给它,这是原始的 html。然后在函数中,我们得到原始 html,找到我们的数据并 return 它。这里我们得到 returned 值并将其保存到名为 content
的变量中