📸
Pythonでスクリーンショットを撮ってくれるDiscordbotを作る!
この記事はもともとQiitaに投稿していたものを、Zennバージョンに書き直し、さらに解説を加えたものです。
今回完成させるもの
Discordでサイトのスクリーンショットを出してくれるボットを作ろう!
ご注意: Discord.py入門編ではありません。 アカウント作成については、以下の素晴らしい記事をご覧ください:こちら
環境
- Windows 10(実際動かす環境では、AWS lightsail上のUbuntu)
- Python 3.8 注意:discord.py v2.0がリリース後、Python 3.8以前のバージョンでdiscord.pyは動作しなくなります。
- discord.py 1.7.3
- Chromedriver 自動インストールにて利用できるもの
- Google Chrome 91.0.4472.114
pipのインストール
pip install discord.py chromedriver chromedriver-binary selenium webdriver-manager
実装
さっそく実装していきましょう!まずはスクリーンショット部分です。
"""
モジュールのインポート
"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
Web='https://yahoo.co.jp'
FILENAME = 'screen.png'
"""
------------------------------
Chromeのオプション設定部分:
"""
options=Options()
options.set_headless(True)
options.add_argument('--disable-dev-shm-usage')
options.add_argument('start-maximized')
options.add_argument('disable-infobarse')
options.add_argument('--disable-extensions')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.binary_location='Chromeがあるとこ'
driver = webdriver.Chrome(
ChromeDriverManager().install(), options=options)
"""
------------------------------
撮影:
"""
driver.get(web)
driver.set_window_size(1280, 720)
driver.save_screenshot(FILENAME)
driver.quit()
driverはChromeDriverManagerが自動で更新、インストールをしてくれます。
ただし、速度が少々遅くなることがあります。(今のところ実際に不便は感じていません)
このままの状態でも使用することができます。このような画像が撮れます:
Discordボットに移植する
最低限動くようにはなっています。
import discord
from discord.ext import commands
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import aiohttp
import asyncio
from webdriver_manager.chrome import ChromeDriverManager
bot = commands.Bot(command_prefix='!',activity=discord.Activity(name='起動中!',type=discord.ActivityType.watching))
bot.session = aiohttp.ClientSession(
headers={
'User-Agent': 'Discordbot/T-taku; aiohttp on Python 3.8;'
},
skip_auto_headers=['User-Agent'],
loop=bot.loop
)
@bot.event
async def on_ready():
#ログイン
print('Login infomation>>>')
print(bot.user.name)
print(bot.user.id)
print('------')
@bot.event
async def on_message(message):
ctx = await bot.get_context(message)#ctxをとる
if message.author.bot:
return #Botには反応しない
await bot.invoke(ctx)
async def get_ss(ctx,web):
try:
options=Options()
options.set_headless(True)
options.add_argument('--disable-dev-shm-usage')
options.add_argument('start-maximized')
options.add_argument('disable-infobarse')
options.add_argument('--disable-extensions')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.binary_location='Chromeがある場所'
driver = webdriver.Chrome(
ChromeDriverManager().install(), options=options)
if not 'http' in str(url):
try:
await bot.loop.run_in_executor(None, functools.partial(driver.get, 'https://'+str(url)))
except:
await bot.loop.run_in_executor(None, functools.partial(driver.get, 'https://'+str(url)))
else:
await bot.loop.run_in_executor(None, functools.partial(driver.get, str(url)))
if 'IP' in driver.page_source:
await ctx.send('このWebページにはアクセスできません。')
else:
await bot.loop.run_in_executor(None, functools.partial(driver.set_window_size, 1280, 720))
await bot.loop.run_in_executor(None, functools.partial(driver.save_screenshot, 'screenshot.png'))
await bot.loop.run_in_executor(None, driver.quit)
file = discord.File('screenshot.png', filename='image.png')
embed = discord.Embed(title='スクリーンショット', description=f'{web}')
embed.set_image(url='attachment://image.png')
await ctx.send(file=file,embed=embed)
driver.quit()
except:
await ctx.send('エラーが発生していたため、アクセスができませんでした。')
@bot.command()
@commands.cooldown(1, 15, type=commands.BucketType.user)
async def ss(ctx, web):
await get_ss(web, ctx)
bot.run('TOKEN HERE')
IPと書いてあるところにサーバーのIPなどを入れておくと、サーバーのIPが公開されているサイトにアクセスできないようにする仕組みです。
ちなみに、非同期処理をしてないと、同時にコマンドが実行された場合ほぼほぼ100%の確率で、ボットが落ちます(オフラインになる)。そのため、しっかり非同期処理をしておきましょう。
感謝
- プログラムの確認をしてくれたjun50さん。(@jun50_python)
- 記事を読んでくれた全ての方々。
Discussion
えーと
options.set_headless(True)が
selenium4ではoptions.headless = Trueになります
selenium4はseleniumの最新バージョンです。