[PYTHON] Collectez un grand nombre d'images à l'aide de l'API de recherche d'images de Bing

2017-09-11 1.36.33.png

Je souhaite collecter 1000 images pour l'apprentissage automatique. Donc, cette fois, l'API du moteur de recherche "[API Bing Image Search](https://azure.microsoft.com/ja-jp/services/cognitive-services/bing-image-search-" fournie par Bing (Microsoft) Collectons des images avec Python3 en utilisant "api /)".

L'API de recherche d'images Bing dispose d'un outil de test sur ici.

Créez un compte Microsoft

Tout d'abord, créez un décompte Microsoft pour obtenir la clé API nécessaire pour accéder à l'API. Pour être honnête, c'est ennuyeux.

Il semble que Microsoft tente d'unifier divers services dans le système «cognitif ●●», et il semble que les noms des services existants aient changé, qu'ils aient déménagé et que les versions aient changé. On dit qu'une nouvelle version de l'API Bing Search v5 a également été publiée à partir du 1er juillet 2016, donc même si vous recherchez sur Google sur le net, il est difficile de comprendre quelle est la méthode d'enregistrement (directe) actuelle après tout.

Ichiou Les étapes suivantes semblent être le minimum requis, veuillez donc les essayer. (Vous devez peut-être créer un autre compte.)

Soit dit en passant, pour créer un compte (inscrivez-vous à Microsoft Azure), comme avec Google Cloud Platform, l'enregistrement de la carte de crédit est requis pour le moment même si elle est utilisée dans le niveau gratuit (bien sûr, aucune facturation n'est requise si elle fait partie du niveau gratuit).

De plus, la nouvelle inscription est accompagnée d'un coupon de 200 $ qui ne peut être utilisé que pendant 30 jours. Pour le moment, vous avez l'impression de pouvoir l'utiliser assez gratuitement pour collecter des images pour le plaisir.

Après le niveau gratuit, il semble que vous serez facturé 3 $ pour 1000 transactions (jusqu'à 150 images peuvent être acquises en une transaction) (* dans le cas de la facturation API de niveau le plus bas de S1). Cliquez ici pour obtenir des informations sur les tarifs (https://azure.microsoft.com/en-us/pricing/details/cognitive-services/search-api/web/). C'est moins cher que le prix de "l'API de recherche de coupes" qui est une API de recherche d'images de Google.

procédure

2017-09-10 16.27.34.png

2017-09-10 15.14.09.png

Cliquez sur "Démarrer gratuitement" en bas à gauche. Créez un compte comme on vous le dit

Après avoir créé un compte, vous serez redirigé vers cette page de Microfost Azure.

2017-09-10 15.19.57.png

Cliquez sur le bouton bleu intitulé "Portail" en haut à droite.

Accédez à la page du tableau de bord qui gère l'API à utiliser.

2017-09-10 15.55.09.png

Vous pouvez définir une nouvelle API à utiliser à partir de "+ Nouveau" dans le menu de gauche.

Recherchez "Bing Search APIs" dans la fenêtre de recherche et cliquez sur les résultats.

2017-09-10 16.05.18.png

Entrez les informations suivantes de Créer, vérifiez confirmer et "Créer".

Si "Créer" réussit, un panneau avec le nom de Nom apparaîtra sur le tableau de bord, alors cliquez dessus.

Cliquez car il y a des "Clés" dans le menu de gauche de la destination cliquée

2017-09-10 16.16.15.png

Notez que "KEY 1" qui apparaît là est la clé requise pour accéder à l'API (probablement "KEY 2" est également ok)

code

Mettez le code qui fonctionne (bing_api.py) pour le moment. (Le script le plus minimal requis pour accéder à l'API est ici) Ici, à titre d'exemple, collectons 1000 images qui sont capturées par le mot de recherche "chat" (japonais). La version Python est 3.5.2 et elle exécute simplement python3 bing_api.py.

Lorsqu'ils sont exécutés, les répertoires nommés corr_table, ʻimgs et pickle_files seront créés sous le répertoire spécifié par save_dir_path`, et chaque donnée sera générée sous ce répertoire.

bing_api.py


# -*- coding: utf-8 -*-
import http.client
import json
import re
import requests
import os
import math
import pickle
import urllib
import hashlib
import sha3


def make_dir(path):
    if not os.path.isdir(path):
        os.mkdir(path)


def make_correspondence_table(correspondence_table, original_url, hashed_url):
    """Create reference table of hash value and original URL.
    """
    correspondence_table[original_url] = hashed_url


def make_img_path(save_dir_path, url):
    """Hash the image url and create the path

    Args:
        save_dir_path (str): Path to save image dir.
        url (str): An url of image.

    Returns:
        Path of hashed image URL.
    """
    save_img_path = os.path.join(save_dir_path, 'imgs')
    make_dir(save_img_path)

    file_extension = os.path.splitext(url)[-1]
    if file_extension.lower() in ('.jpg', '.jpeg', '.gif', '.png', '.bmp'):
        encoded_url = url.encode('utf-8') # required encoding for hashed
        hashed_url = hashlib.sha3_256(encoded_url).hexdigest()
        full_path = os.path.join(save_img_path, hashed_url + file_extension.lower())

        make_correspondence_table(correspondence_table, url, hashed_url)

        return full_path
    else:
        raise ValueError('Not applicable file extension')


def download_image(url, timeout=10):
    response = requests.get(url, allow_redirects=True, timeout=timeout)
    if response.status_code != 200:
        error = Exception("HTTP status: " + response.status_code)
        raise error

    content_type = response.headers["content-type"]
    if 'image' not in content_type:
        error = Exception("Content-Type: " + content_type)
        raise error

    return response.content


def save_image(filename, image):
    with open(filename, "wb") as fout:
        fout.write(image)


if __name__ == "__main__":
    save_dir_path = '/path/to/save/dir'
    make_dir(save_dir_path)

    num_imgs_required = 1000 # Number of images you want. The number to be divisible by 'num_imgs_per_transaction'
    num_imgs_per_transaction = 150 # default 30, Max 150
    offset_count = math.floor(num_imgs_required / num_imgs_per_transaction)

    url_list = []
    correspondence_table = {}

    headers = {
        # Request headers
        'Content-Type': 'multipart/form-data',
        'Ocp-Apim-Subscription-Key': 'xxxxxxxxxxxxxxxxxxxxxxxxxxx', # API key
    }

    for offset in range(offset_count):

        params = urllib.parse.urlencode({
            # Request parameters
            'q': 'Chat',
            'mkt': 'ja-JP',
            'count': num_imgs_per_transaction,
            'offset': offset * num_imgs_per_transaction # increment offset by 'num_imgs_per_transaction' (for example 0, 150, 300)
        })

        try:
            conn = http.client.HTTPSConnection('api.cognitive.microsoft.com')
            conn.request("POST", "/bing/v5.0/images/search?%s" % params, "{body}", headers)
            response = conn.getresponse()
            data = response.read()

            save_res_path = os.path.join(save_dir_path, 'pickle_files')
            make_dir(save_res_path)
            with open(os.path.join(save_res_path, '{}.pickle'.format(offset)), mode='wb') as f:
                pickle.dump(data, f)

            conn.close()
        except Exception as err:
            print("[Errno {0}] {1}".format(err.errno, err.strerror))

        else:
            decode_res = data.decode('utf-8')
            data = json.loads(decode_res)

            pattern = r"&r=(http.+)&p=" # extract an URL of image

            for values in data['value']:
                unquoted_url = urllib.parse.unquote(values['contentUrl'])
                img_url = re.search(pattern, unquoted_url)
                if img_url:
                    url_list.append(img_url.group(1))

    for url in url_list:
        try:
            img_path = make_img_path(save_dir_path, url)
            image = download_image(url)
            save_image(img_path, image)
            print('saved image... {}'.format(url))
        except KeyboardInterrupt:
            break
        except Exception as err:
            print("%s" % (err))

    correspondence_table_path = os.path.join(save_dir_path, 'corr_table')
    make_dir(correspondence_table_path)

    with open(os.path.join(correspondence_table_path, 'corr_table.json'), mode='w') as f:
        json.dump(correspondence_table, f)

Explication partielle du code

À propos des paramètres

Le nombre d'images à acquérir dans une transaction peut être spécifié par count in params (la valeur par défaut est 35 images, Max est 150 images dn760791.aspx # Anchor_2)) Cependant, il semble qu'un nombre inférieur au nombre spécifié soit effectivement renvoyé. Pour acquérir les images suivantes, passez au numéro à partir du nombre spécifié par ʻoffset et démarrez l'acquisition. ʻOffset commence à 0 et boucle jusqu'au nombre spécifié par num_imgs_required. Plus précisément, si vous spécifiez 150 pour count et essayez d'extraire un total de 450 images, spécifiez 0, 150, 300, 450 pour ʻoffset` pendant la boucle. (L'explication officielle de «count» et «offset» est ici)

À propos du fichier de résultats

Lorsque python3 bing_api.py est exécuté, trois répertoires, corr_table, ʻimgs et pickle_files, sont créés sous le répertoire spécifié par save_dir_path`, et chaque donnée est générée sous ce répertoire.

Pour une liste des paramètres de recherche autres que q, cliquez ici (https://msdn.microsoft.com/en-us/library/dn760791.aspx#Anchor_2)

Type d'image cible

Ici, seules les images avec des extensions de jpg, jpeg, gif, png, bmp sont ciblées pour l'acquisition.

À propos du nom de fichier lors de l'enregistrement de l'image

Les noms de fichiers image à enregistrer peuvent être des numéros de série sans penser à rien, mais comme ce sont des images utilisées pour l'apprentissage automatique, j'aimerais omettre les mêmes images autant que possible.

Par conséquent, j'ai essayé de changer le nom de l'image enregistrée en URL au moment de l'acquisition de l'image afin que les noms en double soient écrasés au moment de l'enregistrement, mais il existe un fichier dont l'URL est trop longue (le nom du fichier devient long), donc lors de l'enregistrement Il y avait quelque chose qui me gênait.

En guise de contre-mesure, [traitement de hachage](http://e-words.jp/w/%E3%83%8F%E3%83%83%E3%82%B7%E3] pour l'URL au moment de l'acquisition de l'image % 83% A5% E5% 8C% 96.html) a été effectuée.

Le hachage est à l'origine utilisé pour le cryptage, mais il se convertit en une chaîne de caractères d'environ 65 caractères quel que soit le nombre d'origine de caractères et a la particularité de générer la même chaîne de caractères à partir du même contenu, donc ceci Vous pouvez utiliser pour raccourcir le nom du fichier et en même temps écraser le fichier image avec le même contenu qu'un doublon. J'ai utilisé hashlib pour hacher python, et je me suis référé à ce blog pour sha3 de l'algorithme de hachage.

exemple de conversion de hachage


http://hogehogehogehoge~~~/cat.jpg (URL longue)->hachage->Génère une chaîne de symboles ① d'environ 65 chiffres
http://fugafugafugafuga~~~/cat2.jpg (URL longue)->hachage->Génère une chaîne de symboles ② d'environ 65 chiffres
http://hogehogehogehoge~~~/cat.jpg (URL longue)->hachage->Génère la même chaîne de symboles à 65 chiffres que ①

Résultats et impressions

Comme mentionné ci-dessus, lorsque j'ai frappé l'API pour obtenir 1000 images avec le mot-clé "chat", j'ai pu obtenir 824 images de chat en conséquence. Bien qu'il n'ait pas atteint un peu les 1000 feuilles, je pense que c'est une perte raisonnable compte tenu du fait que l'extension d'image à acquérir est limitée et que les images en double sont omises. (De plus, travailler comme voir l'image de la poubelle et la jeter commence à partir d'ici ...)

Cependant, d'un point de vue différent, cela signifie également que vous ne pouvez obtenir qu'environ 800 images de "chat", ce qui est probablement l'image la plus inondée sur Internet (après cela, même si vous spécifiez 2000 images et l'exécutez). A également confirmé que seulement 800 feuilles environ peuvent être obtenues)

Donc, même si vous dites "Je veux 3000 images de chats", il semble assez difficile de toucher l'API et de les collecter. J'ai l'impression que je peux obtenir un peu plus en combinant des mots clés comme "Cat Egypt", mais il semble que ce ne sera pas tellement.

Aussi, je voulais rechercher un mot qui semble avoir peu d'images sur le net, ce qui est un peu plus de niche, et obtenir l'image, mais dans le cas d'un mot de recherche de niche, le résultat de la recherche sur google est plus ciblé que bing. Il me semblait qu'il y avait beaucoup d'images (peut-être à cause de mon esprit ...). Après tout, la quantité et le type d'images pouvant être obtenues peuvent différer selon le moteur de recherche.

À titre de test, j'essaierai également "API de recherche personnalisée" de google et résumerai les résultats.

(Ajouté le 20170925) J'ai écrit → Collecter un grand nombre d'images en utilisant l'API de recherche d'images de Google (20170926 postscript) J'ai écrit un article de synthèse → Résumé des circonstances de collecte d'images chez Yahoo, Bing, Google

Github

Le même contenu que ci-dessus est également publié sur Github. Veuillez vous référer à README car seule la méthode de spécification de la clé API et de l'ID du moteur de recherche est différente.

référence

Recommended Posts

Collectez un grand nombre d'images à l'aide de l'API de recherche d'images de Bing
Collection d'images à l'aide de l'API Google Custom Search
Téléchargement anonyme d'images à l'aide de l'API Imgur (à l'aide de Python)
Collecter des images pour l'apprentissage automatique (API Bing Search)
Collectez des images à l'aide d'icrawler
Je voulais collecter beaucoup d'images, j'ai donc essayé d'utiliser "google image download"
[Go language] Collectez et enregistrez des images Vtuber à l'aide de l'API Twitter
Collectez des informations sur les produits et traitez les données à l'aide de l'API de recherche de produits Rakuten [Python]
Exporter les résultats de la recherche de publication dans un fichier à l'aide de l'API Mattermost
Capture d'image de Firefox en utilisant Python
Jugement de l'image rétroéclairée avec OpenCV
La loi des nombres en python
Reconnaissance d'image des fruits avec VGG16
Script Python qui collecte automatiquement des images typiques à l'aide de la recherche d'images Bing
Python: principes de base de la reconnaissance d'image à l'aide de CNN
Estimation de catégorie à l'aide de l'API de reconnaissance d'image de docomo
Python: Application de la reconnaissance d'image à l'aide de CNN
Transcription d'images avec l'API Vision de GCP
Enregistrer l'image du chien à partir de la recherche d'images Google
Connaissance de l'utilisation de l'API de données Aurora Severless
Enregistrez automatiquement les images de vos personnages préférés à partir de la recherche d'images Google avec Python