[PYTHON] Erstellen Sie einen Twitter-BOT-Dienst mit der GAE / P + Tweepy + RIOT-API! (Teil 2)

Zusammenfassung

In Fortsetzung von Teil 1 möchte ich im zweiten Teil auf verschiedene APIs verweisen und den BOT-Dienst betreiben. Der Quellcode wird unter GitBucket und das fertige Produkt unter hier betrieben.

Sequentielle Verarbeitung mit Task Queue

Da die Verwendung der API zur Überwachung der Kampfaufzeichnungen jedes Benutzers und zur Veröffentlichung auf Twitter bei Aktualisierungen eingeschränkt ist, muss der auszuführende Prozess in Sekundenintervallen gesteuert werden. Da Cron, das später beschrieben wird, nur in einem Mindestintervall von 1 Minute aufgerufen werden kann, verwendet die Verarbeitung jedes Benutzers einen von GAE bereitgestellten Mechanismus namens Task Queue. Als Image der Task-Warteschlange werden die Tasks in einen Container namens Bucket geworfen, und die Tasks werden gemäß den Einstellungen in der Reihenfolge verarbeitet, in der sie zuerst platziert wurden. Wenn Sie die Bucket-Größe erhöhen, können Sie parallel verarbeiten. Die Konfigurationsdatei lautet `` `queue.yaml```.

queue.yaml


queue:
- name: tweet #Alles ist gut
  rate: 0.8/s #0 pro Sekunde.8-mal verarbeiten
  bucket_size: 1 #Nummer, die parallel verarbeitet werden soll
  retry_parameters:
    task_retry_limit: 0 #Anzahl der Wiederholungen, wenn die Verarbeitung fehlschlägt

Verwenden Sie nun `add ()`, um eine Aufgabe aus Python tatsächlich in den Bucket zu werfen, der in `queue.yaml``` festgelegt ist. Geben Sie name``` an, das in queue.yaml``` für` queue_name entsprechend` festgelegt ist. Geben Sie die Adresse des aufzurufenden Prozesses in "URL angemessen" an. Sie können auch Parameter übergeben.

launcher.py


from google.appengine.api.taskqueue import add

import webapp2

class modelTask(db.Model): #Aufgaben in die Warteschlange
    resion = db.StringProperty()
    summoner_name = db.StringProperty()
    summoner_id = db.IntegerProperty()
    latest_game = db.IntegerProperty()
    access_key = db.StringProperty()
    access_secret = db.StringProperty()
    date_success = db.DateTimeProperty(auto_now_add=True)
    date = db.DateTimeProperty(auto_now_add=True)

class mainHandler(webapp2.RequestHandler):
    def get(self):
        qs = modelTask.all().order('-date_success')
        for q in qs: #Fügen Sie alle Aufgaben zur Warteschlange hinzu
            add(queue_name='tweet', url='/tweet', params={'qid': q.key().id()})

app = webapp2.WSGIApplication([ ('/launcher', mainHandler) ])

Implementieren Sie als Nächstes den Prozess, der aufgerufen wird, wenn die Wende in der Task-Warteschlange erfolgt, die in "URL entsprechend" angegeben ist. Wird von der POST-Methode aus der Task-Warteschlange aufgerufen.

tweet.py


#! -*- coding: utf-8 -*-
from google.appengine.ext import db
from google.appengine.api.urlfetch import fetch
from django.utils.simplejson import loads

import webapp2, tweepy
from datetime import datetime

from laucher import modelTask

CONSUMER_KEY = '********************'
CONSUMER_SECRET = '**************************************'
RIOT_KEY = '***********************************'

class mainHandler(webapp2.RequestHandler):
    def post(self):
        getGame(long(self.request.get('qid')))

def getGame(qid):
    q = modelTask().get_by_id(qid, parent=None)
    #Rufen Sie die RIOT-API auf
    result = fetch('https://prod.api.pvp.net/api/lol/'+q.resion+'/v1.3/game/by-summoner/'+str(q.summoner_id)+'/recent?api_key='+RIOT_KEY)
    if result.status_code == 200:
        #Legen Sie verschiedene Werte fest, die von der API erhalten wurden
        j = loads(result.content)['games'][0]
        if j['stats']['win'] == True:
            win = 'Sieg'
        else:
            win = 'Niederlage'
        try:
            kill = str(j['stats']['championsKilled'])
        except:
            kill = '0'
        try:
            death = str(j['stats']['numDeaths'])
        except:
            death = '0'
        try:
            assist = str(j['stats']['assists'])
        except:
            assist = '0'

        game_type = j['subType']

        #Poste auf Twitter, wenn es in der letzten Kampfzeit ein Update gibt
        if j['createDate'] > q.latest_game:
            q.latest_game = j['createDate']
            q.put()
            if tweet(q.summoner_name+'Herr spätestens'+game_type+'Der Kampfrekord ist'+kill+'töten'+death+'Tod'+assist+'Helfen'+win+'ist. http://tol.orfx.jp #Tweet_of_Legends', q.access_key, q.access_secret):
                q.date_success = datetime.now()
                q.put()

#Twitter-Nachbearbeitung
def tweet(message, access_key, access_secret):
    try:
        auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
        auth.set_access_token(access_key, access_secret)
        api = tweepy.API(auth_handler=auth, api_root='/1.1', secure=True)
        api.update_status(status=message)
        
        return True
    except:
        return False

app = webapp2.WSGIApplication([ ('/tweet', mainHandler) ])

Regelmäßige Bearbeitung mit Cron

Ich verwende Cron, weil ich den Vorgang des regelmäßigen Hinzufügens der obigen Aufgabe zur Warteschlange aufrufen möchte. Die Konfigurationsdatei lautet `` `cron.yaml```. Dieses Mal werde ich versuchen, es alle 10 Minuten von 1 bis 18 Uhr und ansonsten alle 5 Minuten auszuführen.

cron.yaml


cron:
- description: tweet job
  url: /launcher
  schedule: every 10 minutes from 1:00 to 17:59
  timezone: Asia/Tokyo #Vergessen Sie nicht die Zeitzone, wenn Sie die Zeit angeben
  
- description: tweet job
  url: /launcher
  schedule: every 5 minutes from 18:00 to 0:59
  timezone: Asia/Tokyo

Ressourcenverteilung mit Backend

Wenn Sie mit dieser Cron-Einstellung (alle 5 bis 10 Minuten) arbeiten, wird die Startzeit der Instanz übrigens in Schritten von 15 Minuten berechnet, sodass die Startzeit der Frontend-Instanz definitiv 24 Stunden oder mehr beträgt. Darüber hinaus wird die Verarbeitung der Registrierungsseite usw. hinzugefügt, sodass ich mir Sorgen über die 28 Stunden des kostenlosen Frames (Stand März 2014) mache. Nutzen wir also das Backend. Das Backend ist ursprünglich ein Mechanismus für Arbeiten hinter den Kulissen wie Stapelverarbeitung und asynchrone Verarbeitung. Dieses Mal wird es jedoch lediglich verwendet, um die Startzeit der Instanz (9 Stunden) zu verdienen. Die Konfigurationsdatei lautet `` `backend.yaml```.

backend.yaml


backends:
- name: tweet #Alles ist gut
  class: B1 #Verarbeitungsressourcen minimieren
  options: dynamic #Machen Sie die Instanz nicht resident

Wenn Cron den Prozess unterstützen soll, geben Sie `` `target``` an. Dieses Mal werde ich es mit Backend von 18 Uhr bis 1 Uhr morgens bearbeiten.

cron:
- description: tweet job
  url: /launcher
  schedule: every 10 minutes from 1:00 to 17:59
  timezone: Asia/Tokyo
  
- description: tweet job
  url: /launcher
  schedule: every 5 minutes from 18:00 to 0:59
  timezone: Asia/Tokyo
  target: tweet #backend.Yaml Name

TaskQueue kann auch vom Backend verarbeitet werden, indem `add (target =)` angegeben wird. Verwenden Sie get_backend (), um zu sehen, ob Sie mit Backend arbeiten. Wenn das Backend gestartet wird, wird `` `/ _ah / start``` zwangsweise aufgerufen. Da es zuerst aufgerufen wird, können Sie den Prozess beim Start beschreiben, aber dieses Mal werden wir den leeren Prozess beschreiben.

launcher.py


from google.appengine.api.taskqueue import add
from google.appengine.api.backends import get_backend

import webapp2

class modelTask(db.Model):
    resion = db.StringProperty()
    summoner_name = db.StringProperty()
    summoner_id = db.IntegerProperty()
    latest_game = db.IntegerProperty()
    access_key = db.StringProperty()
    access_secret = db.StringProperty()
    date_success = db.DateTimeProperty(auto_now_add=True)
    date = db.DateTimeProperty(auto_now_add=True)

class mainHandler(webapp2.RequestHandler):
    def get(self):
        qs = modelTask.all().order('-date_success')
        target = get_backend()
        if target is None: #Wenn es vom Backend gestartet wird, ist TaskQueue dasselbe.
            for q in qs:
                add(queue_name='tweet', url='/tweet', params={'qid': q.key().id()})
        else:
            for q in qs:
                add(queue_name='tweet', url='/tweet', params={'qid': q.key().id()}, target='tweet')

class startHandler(webapp2.RequestHandler): #Wird beim Start des Backends aufgerufen
    def get(self):
        return

app = webapp2.WSGIApplication([ ('/launcher', mainHandler), ('/_ah/start', startHandler) ])

Reduzieren Sie den Ressourcenverbrauch mit Memcache

Memcache kann verwendet werden, um den Ressourcenverbrauch für Prozesse, die den Datenspeicher häufig durchsuchen, ihn jedoch selten aktualisieren, erheblich zu reduzieren. In RIOT API game-v1.3 wird Champion als ID zurückgegeben, daher müssen Sie die ID basierend auf den Informationen in champ-v1.1 in einen Namen konvertieren. Da Sie die API nicht häufig aufrufen können, werden die von champ-v1.1 erfassten Informationen einmal im Datenspeicher gespeichert. Kopieren Sie dann die in Memcache gespeicherten Informationen. Verwenden Sie `memcache.add (Schlüssel, Wert)`, um Daten zu Memcache hinzuzufügen.

champion.py


from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.api.urlfetch import fetch
from django.utils.simplejson import loads

import webapp2

RIOT_KEY = '***********************************'

class modelChampion(db.Model): #Champion Informationsspeichermodell
    name = db.StringProperty()
    date = db.DateTimeProperty(auto_now_add=True)

class mainHandler(webapp2.RequestHandler):
    def get(self):
        #Champion Informationsbeschaffung
        result = fetch('https://prod.api.pvp.net/api/lol/na/v1.1/champion?api_key='+RIOT_KEY)
        if result.status_code == 200:
            js = loads(result.content)['champions']
            for j in js:
                #Champion Informationsspeicher
                modelchampion = modelChampion().get_or_insert(str(j['id']))
                modelchampion.name = j['name']
                modelchampion.put()

                #Kopieren Sie die Championinformationen in Memcache
                memcache.add("champion_"+str(j['id']), j['name'], 86399)

app = webapp2.WSGIApplication([ ('/champion', mainHandler) ], debug=True)

Verwenden Sie `memcache.get (Schlüssel)`, um auf die zu Memcache hinzugefügten Daten zu verweisen. Da die zu Memcache hinzugefügten Daten möglicherweise verloren gehen, muss die Verarbeitung zu diesem Zeitpunkt beschrieben werden. Fügen wir nun den Namen des Champions zum veröffentlichten Inhalt in tweet.py hinzu.

tweet.py


from google.appengine.api import memcache
from champion import modelChampion

def getGame(qid):
    q = modelQueue().get_by_id(qid, parent=None)
    result = fetch('https://prod.api.pvp.net/api/lol/'+q.resion+'/v1.3/game/by-summoner/'+str(q.summoner_id)+'/recent?api_key='+RIOT_KEY)
    if result.status_code == 200:
        j = loads(result.content)['games'][0]
        if j['stats']['win'] == True:
            win = 'Sieg'
        else:
            win = 'Niederlage'
        try:
            kill = str(j['stats']['championsKilled'])
        except:
            kill = '0'
        try:
            death = str(j['stats']['numDeaths'])
        except:
            death = '0'
        try:
            assist = str(j['stats']['assists'])
        except:
            assist = '0'

        #Holen Sie sich Champion-Informationen von Memcache
        champion = memcache.get("champion_"+str(j['championId']))
        if champion is None: #Wenn Sie keine Championinformationen aus Memcache abrufen können, aus dem Datenspeicher
            champion = modelChampion.get_by_key_name(str(j['championId'])).name

        game_type = j['subType']
        
        if j['createDate'] > q.latest_game:
            q.latest_game = j['createDate']
            q.put()
            if tweet(q.summoner_name+'Herr spätestens'+game_type+'Der Kampfrekord ist'+champion+'damit'+kill+'töten'+death+'Tod'+assist+'Helfen'+win+'damitす 。 http://tol.orfx.jp #Tweet_of_Legends', q.access_key, q.access_secret):
                q.date_success = datetime.now()
                q.put()

Zusammenfassung

Dies ist das erste mit GAE erstellte Memorandum of Application. Sobald Sie den Dreh raus haben, ist es sehr einfach, ab dem nächsten Mal eine App zu erstellen. Es wird daher empfohlen!

Recommended Posts

Erstellen Sie einen Twitter-BOT-Dienst mit der GAE / P + Tweepy + RIOT-API! (Teil 1)
Erstellen Sie einen Twitter-BOT-Dienst mit der GAE / P + Tweepy + RIOT-API! (Teil 2)
Schritte zum Erstellen eines Twitter-Bots mit Python
Ich habe einen Twitter BOT mit GAE (Python) gemacht (mit einer Referenz)
Erstellen Sie mithilfe der Twitter-Streaming-API einen Echtzeit-Bot für die automatische Antwort
Erstellen Sie einen Twitter-BOT mit dem GoogleAppEngine SDK für Python
Ich habe einen Twitter-Bot mit Go x Qiita API x Lambda erstellt
[LINE Messaging API] Erstellen Sie einen BOT, der eine Verbindung zu jemandem mit Python herstellt
Erstellen Sie einen Bot, der Twitter-Trends verstärkt
Erstellen Sie einen Webdienst mit Docker + Flask
Machen wir einen Twitter-Bot mit Python!
Tweet die Wettervorhersage mit Bot Teil 2
Machen Sie Twitter Trend Bot mit Heroku + Python
Erstellen Sie mit Minette für Python einen LINE BOT
[Life Hack] Anna-Unterstützungsbot für Frauen mit Twitter-API
Erstellen Sie eine Tweet-Heatmap mit der Google Maps-API
[LINE Messaging API] Erstellen Sie einen Papageienrückgabe-BOT mit Python
Erstellen Sie einen Slack Bot
Ich habe ein Skript geschrieben, um mit AWS Lambda + Python 2.7 schnell eine Entwicklungsumgebung für Twitter Bot zu erstellen
Erstellen Sie eine App für maschinelles Lernen mit ABEJA Platform + LINE Bot
Erstellen Sie einen Mastodon-Bot mit einer Funktion, die automatisch mit Python antwortet
Tornado - Erstellen wir eine Web-API, die JSON problemlos mit JSON zurückgibt
Erstellen Sie eine Web-API, die Bilder mit Django liefern kann
Erstellen Sie mit Django eine API für die soziale Integration von Smartphone-Apps
Erstellen Sie eine API mit Django
Verwenden Sie die Twitter-API mit Python
Erstellen Sie eine Homepage mit Django
Unterstützen Sie sich mit der Twitter API
Erstellen Sie ein Verzeichnis mit Python
Erfolgreiches update_with_media mit Twitter API
[AWS Hands-on] Erstellen wir einen Promi-Identifikationsdienst mit einer serverlosen Architektur!
Erstellen Sie eine Wortwolke mit nur positiven / negativen Wörtern auf Twitter
Versuchen Sie, einen Artikel von Qiita mit der REST-API [Umweltvorbereitung] zu erstellen.
Erstellen Sie eine REST-API, um dynamodb mit dem Django REST Framework zu betreiben
So erstellen Sie mit AWS Lambda eine serverlose API für maschinelles Lernen
Anfänger machen einen automatischen Bitcoin-Handelsbot, der viel Geld anstrebt! Teil 2 [Transaktion mit API]