Ich habe einen Bot erstellt, der Bilder durchsuchen kann, also werde ich das Wissen zu diesem Zeitpunkt schreiben.
Auf diese Weise wird nach einem Bild aus dem angegebenen Schlüsselwort gesucht und eingefügt. Die Installation kann von [hier] aus erfolgen (https://discord.com/api/oauth2/authorize?client_id=766774601904029726&permissions=8&scope=bot). Bitte zögern Sie nicht, uns zu kontaktieren Quellcode (Github)
Erstellt mit Bezug auf diesen Artikel tat. Wenn Sie Discord.py nicht berührt haben, empfehlen wir Ihnen, dies zuerst zu lesen.
Verwenden Sie urllib, um nach Bildern zu suchen und HTML zu erhalten. Zu diesem Zeitpunkt ändert sich der Inhalt von HTML. Geben Sie daher unbedingt User-Agent an.
find_image.py
from urllib import request as req
from urllib import parse
def find_image(keyword):
urlKeyword = parse.quote(keyword)
url = 'https://www.google.com/search?hl=jp&q=' + urlKeyword + '&btnG=Google+Search&tbs=0&safe=off&tbm=isch'
headers = {"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0",}
request = req.Request(url=url, headers=headers)
page = req.urlopen(request)
html = page.read()
page.close()
return html
Wenn Sie ein Bild durch Scraping erhalten, können Sie es normalerweise über das img-Tag abrufen. Bei der Google-Bildsuche können Sie jedoch nur ein komprimiertes Bild abrufen. Um das Originalbild zu erhalten, müssen Sie auf klicken, um es wie diesen Artikel auf Selen usw. zu erhalten. Diesmal nehme ich eine andere Methode, um die Last und Geschwindigkeit zu berücksichtigen. Als Werbung habe ich einen Artikel über die Tipps zur Beschleunigung von Beautiful Soup geschrieben. Wenn Sie möchten, lesen Sie bitte hier.
Wenn User-Agent im Browser angegeben ist, wird der Methodenaufruf wie unten gezeigt im sctipt-Tag implementiert. Verwenden Sie ihn daher.
python
<script nonce>
AF_initDataCallback({
key: 'ds:1',
isError: false,
hash: '2',
data: [null, [
[
["g_1", [
["Sahne", ["https://encrypted-tbn0.gstatic.com/images?q\u003dtbn%3AANd9GcR_QK2ghJ5WWcj-Tcf9znnP6_rZwe7f2MCwWUERoVqVLNRFsj4D\u0026usqp\u003dCAU", null, null, true, [null, 0], false, false], "/search?q\u003d%E3%83%97%E3%83%AA%E3%83%B3\u0026tbm\u003disch\u0026chips\u003dq:%E3%83%97%E3%83%AA%E3%83%B3,g_1:%E7%94%9F+%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%A0:FuBfrMHhliU%3D", null, null, [null, null, null, null, "q:Pudding,g_1:Sahne:FuBfrMHhliU\u003d"], 0],
["Gemischtwarenladen", ["https://encrypted-tbn0.gstatic.com/images?q\u003dtbn%3AANd9GcThveHaG9uvSFj6QwXIVDoJPs9P3KjNdnl-I35Wf0WzAKNffK_m\u0026usqp\u003dCAU", null, null, true, [null, 0], false, false], "/search?q\u003d%E3%83%97%E3%83%AA%E3%83%B3\u0026tbm\u003disch\u0026chips\u003dq:%E3%83%97%E3%83%AA%E3%83%B3,g_1:%E3%82%B3%E3%83%B3%E3%83%93%E3%83%8B:tHwRIJyFAco%3D", null, null, [null, null, null, null, "q:Pudding,g_1:Gemischtwarenladen:tHwRIJyFAco\u003d"], 1],
.......
Da dies jedoch ein Songwriter ist und die Position bei der Suche für jedes Schlüsselwort unterschiedlich ist, kann es nicht mit xpath oder css selector erfasst werden, es kann nicht eingegrenzt werden, da kein Attribut angegeben ist, und nach dem Erweitern der Variablen Da es im JSON-Format von vorliegt, kann es nicht einfach in JSON-Daten konvertiert werden. Also habe ich ** Gori ** gedrückt. Holen Sie sich zunächst alle Skript-Tags, suchen Sie den Inhalt, der mit AF_initDataCallback beginnt, und formatieren Sie ihn zwangsweise so, dass json ihn lesen kann. Da es sich bei der Struktur jedoch nicht um einen Wörterbuchtyp, sondern um ein Array handelt, wird der Index fest erfasst. Um ehrlich zu sein, ist die Methode des Slekiping unten aufgeführt, aber ich habe bei dieser Implementierung Kompromisse eingegangen, da wie bei diesem Bot Geschwindigkeit erforderlich ist.
find_image.py
import bs4
def scrap_image_urls(html, start = 0, stop = 1)):
soup = bs4.BeautifulSoup(html, 'html.parser', from_encoding='utf8')
soup = soup.find_all('script')
data = [c for s in soup for c in s.contents if c.startswith('AF_initDataCallback')][1]
data = data[data.find('data:') + 5:data.find('sideChannel') - 2]
data = json.loads(data)
data = data[31][0][12][2]
image_urls= [x[1][3][0] for x in data if x[1]]
image_urls= [url for url in image_urls if not is_exception_url(url)][start:stop]
return image_urls
Websites mit Anti-Scraping-Maßnahmen wie Insta werden jedoch abgespielt, da sie die URL nicht erhalten können.
find_image.py
exception_urls = [
'.cdninstagram.com',
'www.instagram.com'
]
def is_exception_url(str):
return any([x in str for x in exception_urls])
Implementierung der Funktion zum Konvertieren des Präfixes (Präfix am Anfang des Befehls). Es gibt viele Möglichkeiten, dies zu tun, aber dieses Mal verwende ich Heroku Postgres. Zuerst habe ich es mit einer JSON-Datei geschafft, aber da Heroku jeden Tag zurückgesetzt wird, wurden die Daten weggeblasen. .. .. Der Bereitstellungsfluss für Heroku ist [Erster eingeführter Artikel](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f#%E3%81%AF%E3%81%98%E3%82%81%E3% Einzelheiten entnehmen Sie bitte 81% AB). ** Sie müssen den Befehl psql installieren. ** ** **
Fügen Sie Add-Ons mit hobby-dev hinzu, einem kostenlosen Plan. Die maximale Anzahl von Aufzeichnungszeilen beträgt 10 KB.
$ heroku addons:create heroku-postgresql:hobby-dev -a [APP_NAME]
Überprüfen Sie zunächst den erstellten Datenbanknamen. Siehe die Add-On-Zeile
heroku pg:info -a discordbot-findimage
Greifen Sie dann auf die Datenbank zu. Bitte verwenden Sie den zuvor erhaltenen Datenbanknamen
heroku pg:psql [DATABASE_NAME] -a [APP_NAME]
Nachdem Sie SQL ausführen können, erstellen Sie eine Tabelle.
create table guilds (
id varchar(255) not null,
prefix varchar(255) not null,
PRIMARY KEY (id)
);
Dieses Mal benutze ich psycopg2. Die Datenbank-URL ist zum Zeitpunkt der Erstellung in der Umgebungsvariablen definiert. Verwenden Sie sie daher.
find_image.py
import psycopg2
db_url = os.environ['DATABASE_URL']
conn = psycopg2.connect(db_url)
discord.Client kann eine Methode im Konstruktor übergeben, also übergeben Sie sie beim Erstellen einer Instanz. In diesem Beispiel wird ** discord.ext.commands.Bot ** verwendet, eine untergeordnete Klasse von discord.Client.
find_image.py
from discord.ext import commands
import psycopg2
defalut_prefix = '!'
table_name = 'guilds'
async def get_prefix(bot, message):
return get_prefix_sql(str(message.guild.id))
def get_prefix_sql(key):
with conn.cursor() as cur:
cur.execute(f'SELECT * FROM {table_name} WHERE id=%s', (key, ))
d = cur.fetchone()
return d[1] if d else defalut_prefix
bot = commands.Bot(command_prefix=get_prefix)
In diesem Fall wird die UPSERT-Abfrage ausgeführt, wenn der Befehl set_prefix ausgeführt wird.
find_image.py
from discord.ext import commands
import psycopg2
table_name = 'guilds'
def set_prefix_sql(key, prefix):
with conn.cursor() as cur:
cur.execute(f'INSERT INTO {table_name} VALUES (%s,%s) ON CONFLICT ON CONSTRAINT guilds_pkey DO UPDATE SET prefix=%s', (key, prefix, prefix))
conn.commit()
@bot.command()
async def set_prefix(ctx, prefix):
set_prefix_sql(str(ctx.guild.id), prefix)
await ctx.send(f'The prefix has been changed from {ctx.prefix} to {prefix}')
Danke, dass Sie so weit gelesen haben! Ich hoffe, es wird hilfreich sein, wenn Sie Discord Bot erstellen und abkratzen!
Recommended Posts