Suite ・ J'ai essayé de créer Slackbot après avoir étudié Python3

introduction

Extrait du précédent "J'ai essayé d'utiliser Slackbot après avoir étudié Python 3" Nous avons amélioré ou ajouté des fonctionnalités.

spécification

  1. À l'aide de l'API Guru Navi, entrez un mot de recherche dans slack et renvoyez l'URL du hit. Si vous tapez "riz Shinagawa Yakitori", l'URL d'une boutique qui ressemble à un restaurant Yakitori à Shinagawa sera retournée. Comme je recherchais par adresse lors de la recherche par mot-clé d'emplacement, le résultat de l'emplacement différent de l'image réelle est renvoyé, j'ai donc changé pour la recherche à l'aide du maître de zone.

  2. Il s'agit d'une recherche de nom de magasin à l'aide de l'API Guru Navi. Si vous tapez "Shop Shinagawa LOL", l'URL de Shinagawa LOL sera retournée. Il s'agit simplement d'une recherche par nom de magasin. Cependant, nous ne pouvons pas gérer les cas où il y a un espace entre eux.

  3. Renvoie l'image radar du nuage de pluie à l'aide de l'API Geocoder de Yahoo et de l'API Static Map. Si vous tapez "pluie Shinagawa", une image de carte avec des nuages de pluie près de Shinagawa sera renvoyée. Pour renvoyer l'image de la carte, utilisez l'API de Slack files.upload.

Environnement etc.

J'ai utilisé Pillow pour travailler avec des fichiers image.

Constitution

slackbot/  ├ plugins/  │ └ slackbot_restapi.py  │ └ restapi.py  │ └ gnaviapi.py  │   └ run.py  └ slackbot_settings.py └ Procfile (fichier pour Heroku) └ runtime.txt (fichier pour Heroku)

Cela n'a pas changé en particulier. Je modifie gnaviapi.py et slackbot_restapi.py. Cependant, la classification et l'organisation en quelque sorte ne sont pas divisées w Je pense que je peux l'écrire un peu plus magnifiquement.

la mise en oeuvre

Cette fois, seuls les changements. Contrairement à la dernière fois, c'est une explication pour chaque spécification.

Recherche de magasin

slackbot_restapi.py


"""
Plugin Program
"""
from io import BytesIO
import requests
from requests.exceptions import RequestException
from PIL import Image
from slackbot.bot import listen_to
from plugins.restapi import RestApi
from plugins.gnaviapi import GnaviApi
import slackbot_settings

@listen_to('riz')
@listen_to('boutique')
def search_restraunt(message):
    """
Recherchez Guru Navi en fonction du message reçu et renvoyez l'URL.
Emplacement: Code maître de la zone M(areacode_m)ou adresse(address)
Mots-clés: mots libres(freeword)ou nom du magasin(name)
    """
    url = 'https://api.gnavi.co.jp/RestSearchAPI/20150630/'
    key = 'YOUR_GNAVI_API_TOKEN'

    gnavi = GnaviApi(url, key)

    search_word = message.body['text'].split()

    if len(search_word) >= 3:
        try:
            params = gnavi.create_params(search_word)

            gnavi.garea_middle_fech()
            search_area = gnavi.garea_middle_search(search_word[1])
            if len(search_area) == 0:
                search_area = {'address': search_word[1]}

            params.update(search_area)
            gnavi.api_request(params)

            for rest_url in gnavi.url_list():
                message.send(rest_url)
        except RequestException:
            message.send('Je ne suis pas entré dans Guru Navi, alors cherchez-le à nouveau plus tard ...( ´Д`)y━ ・~~')
            return
        except Exception as other:
            message.send(''.join(other.args))
            return
    else:
        message.send('↓ Je veux que vous cherchiez comme ça ...( ̄Д ̄)Non')
        message.send('Mot-clé Rice place (les caractères sont séparés par des espaces)')
        message.send('Exemple) Rice Shinagawa Yakitori')

Avec params = gnavi.create_params (search_word), il juge "riz" ou "magasin" et change le paramètre à lancer à l'API en mot libre ou nom de magasin. Utilisez garea_middle_fech () pour rechercher le maître de la zone M de Guru Navi et obtenir l'indicatif régional. garea_middle_search (search_word [1]) renvoie le premier indicatif régional qui correspond au nom de lieu saisi dans Slack. Si vous ne parvenez pas à obtenir l'indicatif régional, nous continuerons à rechercher l'adresse. Le reste est le même que la dernière fois.

gnavapi.py


"""
API Guru Navi
"""
# -*- coding: utf-8 -*-
from requests.exceptions import RequestException
from plugins.restapi import RestApi

class GnaviApi(RestApi):
    """
Classe d'API Guru Navi
    """
    def __init__(self, url, key):
        super().__init__(url)
        self.key = key
        self.garea_s = None

    def create_params(self, search_word):
        """
Modifiez les paramètres de l'API en fonction des mots clés saisis dans Slack.
        """
        params = {
            'format': 'json'
        }

        if search_word[0] == 'riz':
            params['freeword'] = search_word[2]

        elif search_word[0] == 'boutique':
            params['name'] = search_word[2]

        return params

    def url_list(self):
        """
Créez une liste d'URL de restaurant à partir de Response et renvoyez-la.
        """
        json_data = self.response_data.json()
        if 'error' in json_data:
            raise Exception('Je n'ai pas pu le trouver avec ce mot-clé ...(´ ・ ω ・ `)')

        if json_data['total_hit_count'] == '1':
            return [(json_data['rest'])['url']]
        else:
            return [rest_data['url'] for rest_data in json_data['rest']]

    def garea_middle_fech(self):
        """
Obtenez le maître de zone M de l'API Guru Navi.
        """
        garea = RestApi('https://api.gnavi.co.jp/master/GAreaMiddleSearchAPI/20150630/')
        params = {
            'keyid': self.key,
            'format': 'json',
            'lang': 'ja'
        }
        try:
            garea.api_request(params)
            self.garea_s = garea.response_data.json()
            if 'error' in self.garea_s:
                raise Exception('Je ne connais pas l'endroit ...(´ ・ ω ・ `)')
        except RequestException:
            raise RequestException()

    def garea_middle_search(self, area_name):
        """
Depuis l'intérieur de la zone M maître, zone_Obtenez la valeur qui correspond au nom.
(Parce qu'il est strict s'il s'agit d'une correspondance exacte, il s'agit d'une correspondance partielle.)
        """
        result_dict = {}
        for area_s in self.garea_s['garea_middle']:
            if area_s['areaname_m'].find(area_name) >= 0:
                result_dict = {'areacode_m': area_s['areacode_m']}
                break

        return result_dict

↑ Une méthode de recherche d'un maître de zone a été ajoutée à la classe API Guru Navi.

Recherche de nuages de pluie

slackbot_restapi.py


"""
Plugin Program
"""
from io import BytesIO
import requests
from requests.exceptions import RequestException
from PIL import Image
from slackbot.bot import listen_to
from plugins.restapi import RestApi
from plugins.gnaviapi import GnaviApi
import slackbot_settings

def search_restraunt(message):
    """
réduction!!!
    """

@listen_to('pluie')
def search_weather(message):
    """
Obtenez la latitude et la longitude de l'API Geocoder en fonction du message reçu.
Renvoie l'image radar du nuage de pluie de l'API de carte statique en fonction de la latitude et de la longitude.
Adresse de l'emplacement(query)
    """
    url_geocoder = 'https://map.yahooapis.jp/geocode/V1/geoCoder'
    url_staticmap = 'https://map.yahooapis.jp/map/V1/static'
    key_yahoo = 'YOUR_YAHOO_API_TOKEN'

    url_slackapi = 'https://slack.com/api/files.upload'

    geocoder_api = RestApi(url_geocoder)
    staticmap_api = RestApi(url_staticmap)

    search_word = message.body['text'].split()

    try:
        geocoder_api_params = {
            'appid': key_yahoo,
            'query': search_word[1],
            'output': 'json'
        }
        geocoder_api.api_request(geocoder_api_params)
        geocoder_json = geocoder_api.response_data.json()
        if 'Error' in geocoder_json:
            raise Exception('Je ne connais pas l'endroit ...(´ ・ ω ・ `)')
        coordinates = (((geocoder_json['Feature'])[0])['Geometry'])['Coordinates']

        staticmap_api_params = {
            'appid': key_yahoo,
            'lon': (coordinates.split(','))[0],
            'lat': (coordinates.split(','))[1],
            'overlay': 'type:rainfall',
            'output': 'jpg',
            'z': '13'
        }
        staticmap_api.api_request(staticmap_api_params)

        slackapi_params = {
            'token': slackbot_settings.API_TOKEN,
            'channels': 'C5CJE5YBA'
        }

        image_obj = Image.open(BytesIO(staticmap_api.response_data.content), 'r')
        image_obj.save('/tmp/weather.jpg')
        with open('/tmp/weather.jpg', 'rb') as weatherfile:
            requests.post(url_slackapi, data=slackapi_params, files={
                'file': ('weather.jpg', weatherfile, 'image/jpeg')})

    except Exception as other:
        message.send(''.join(other.args))
        return

Contrairement à l'API Guru Navi, le maître de zone ne semble pas exister, donc la latitude et la longitude sont acquises en fonction de l'adresse. Une fois que vous avez la latitude et la longitude, le reste est facile. Il était facile d'obtenir les données d'image ** «obtenir» **. Jusque là ...

De là, j'en étais accro. J'avais peur de ne pas pouvoir télécharger de données d'image sur Slack. Au début, je pensais que j'irais si j'envoyais ʻimage_obj = Image.open (BytesIO (staticmap_api.response_data.content), 'r') , mais c'est totalement inutile. À la suite de divers essais, j'ai réussi à enregistrer une fois le fichier réel, à le lire avec kʻopen () et à envoyer les données. Heroku semble être capable de sauvegarder des fichiers sous / tmp, donc je l'ai sauvegardé sous ʻimage_obj.save ('/tmp/weather.jpg')` et je l'ai rechargé.

Puisque ʻimage_obj était un objet JpgImageFile, ce serait le même que l'objet file, est-ce la cause de la défaite? J'étais inquiet environ 3 jours après avoir configuré PngImageFile ou ʻimage_obj = BytesIO (staticmap_api.response_data.content) puis en utilisant getvalue () et getbuffer ().

スクリーンショット 2017-06-01 23.27.30.png

À la fin

Je vérifie les spécifications de requests.post (), mais je ne sais pas pourquoi le JpgImageFile ne peut pas être envoyé. Je continuerai d'enquêter, mais si quelqu'un le sait, faites-le moi savoir.

Post-scriptum (20170701)

Merci pour votre commentaire

Changer avant


image_obj = Image.open(BytesIO(staticmap_api.response_data.content), 'r')
image_obj.save('/tmp/weather.jpg')
with open('/tmp/weather.jpg', 'rb') as weatherfile:
    requests.post(url_slackapi, data=slackapi_params, files={
        'file': ('weather.jpg', weatherfile, 'image/jpeg')})

Cette partie,

Après le changement


output = BytesIO()
image_obj = Image.open(BytesIO(staticmap_api.response_data.content), 'r')
image_obj.save(output, 'jpeg')
requests.post(slackbot_settings.API_URL, data=slackapi_params, files={
    'file': ('weather.jpg', output.getvalue(), 'image/jpeg')
    })

Je l'ai corrigé et déplacé, et cela a fonctionné! Pourquoi cela n'a-t-il pas fonctionné tel quel? Bref, merci!

Recommended Posts

Suite ・ J'ai essayé de créer Slackbot après avoir étudié Python3
Après avoir étudié Python3, j'ai créé un Slackbot
J'ai essayé de toucher Python (installation)
J'ai essayé de créer diverses "données factices" avec Python faker
J'ai fait un chronomètre en utilisant tkinter avec python
J'ai essayé de créer une interface graphique à trois yeux côte à côte avec Python et Tkinter
J'ai essayé de résumer la gestion des exceptions Python
J'ai essayé d'implémenter PLSA en Python
J'ai essayé d'implémenter la permutation en Python
[Python] J'ai essayé d'implémenter un tri stable, alors notez
J'ai essayé de créer une expression régulière de "temps" en utilisant Python
J'ai essayé d'implémenter PLSA dans Python 2
[3ème] J'ai essayé de créer un certain outil de type Authenticator avec python
Entrée standard Python3 que j'ai essayé de résumer
J'ai essayé de créer une expression régulière de "date" en utilisant Python
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé d'implémenter ADALINE en Python
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé d'implémenter PPO en Python
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[Python] Japonais simple ⇒ J'ai essayé de créer un outil de traduction en anglais
J'ai créé une API Web
[Python] J'ai essayé de calculer TF-IDF régulièrement
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de toucher Python (syntaxe de base)
J'ai essayé de créer une fonction de similitude d'image avec Python + OpenCV
[TCP / IP] Après avoir étudié, essayez de créer un client HTTP avec Python
[AWS] [GCP] J'ai essayé de rendre les services cloud faciles à utiliser avec Python
J'ai essayé de faire un signal avec Raspeye 4 (édition Python)
[Zaif] J'ai essayé de faciliter le commerce de devises virtuelles avec Python
J'ai refactoré "J'ai essayé de faire d'Othello AI lorsque les débutants en programmation ont étudié python"
Je veux faire un jeu avec Python
J'ai essayé d'obtenir des données CloudWatch avec Python
J'ai essayé de sortir LLVM IR avec Python
J'ai essayé de faire de l'IA pour Smash Bra
J'ai essayé d'implémenter TOPIC MODEL en Python
J'ai essayé d'automatiser la fabrication des sushis avec python
Je veux créer du code C ++ à partir de code Python!
J'ai essayé d'implémenter le tri sélectif en python
J'ai créé un jeu ○ ✕ avec TensorFlow
J'ai essayé Python> autopep8
J'ai essayé de déboguer.
J'ai essayé Python> décorateur
J'ai fait une application d'envoi de courrier simple avec tkinter de Python
[Analyse des brevets] J'ai essayé de créer une carte des brevets avec Python sans dépenser d'argent
Python / PEP8> E128 J'ai essayé de résoudre la ligne de continuation sous-indentée pour l'indentation visuelle
[Python] J'ai essayé de créer une IA Shiritori qui améliore le vocabulaire grâce aux batailles
[Introduction à Docker] J'ai essayé de résumer diverses connaissances Docker acquises en étudiant (Windows / Python)
J'ai essayé de faire un "putain de gros convertisseur de littérature"
J'ai essayé de représenter graphiquement les packages installés en Python
Quand j'ai essayé d'introduire python3 dans atom, je suis resté coincé
J'ai essayé de résumer comment utiliser matplotlib de python
J'ai essayé d'implémenter Mine Sweeper sur un terminal avec python
J'ai essayé de démarrer avec le script python de blender_Part 01
J'ai essayé de toucher un fichier CSV avec Python
J'ai essayé de résoudre Soma Cube avec python
J'ai essayé d'implémenter un pseudo pachislot en Python