PythonでBing Search APIを使って画像を検索する
ゆーすけべーさんの本を読んでいたら、「いかにして大量のおっぱい画像をダウンロードするのか」という章があって、高校生がプログラミンを始めるキッカケになったというエピソードに笑えました。若い男性がプログラムに興味を持つきっかけとなるには、ベストな話題かもしれません。
ということで、僕もPythonで画像を検索するプログラムを作ってみました。ところが、1ヶ月前ぐらいに作ったプログラムで、どうやって調べたのか忘れてしまい、ブログに書くためほぼ最初から調べ直しというアホなことをやってます。つぎからはちゃんとメモしておくことにしよう。
プログラムを作るにあたって、同じことをやっている記事がないか、Googleで検索したらBing Search API を使いたいと思ったのでPythonでラッパーを作ってみた – [[ともっくす alloc] init]がヒットしたので参考にしました。
BeingでSearch APIを使うためには、Microsoftアカウントが必要となります。まだ持っていない人も、Bing Search API | Microsoft Azure Marketplaceから、ひと月5,000トランザクション(無料)を選択して表示されるログイン画面からMicrosoftアカウントを取得できます。
無事に購読契約できたら、Microsoft Azure Marketplaceのアカウント情報に表示されるプライマリアカウントキーを記録しておきます。APIでデータ要求するときにサイト認証で使います。
Search APIの使い方はBing API Migration Guide にあります。
実験環境
- ThinkPad X200
- Windows7 Professional 64bit
- Python 2.7.3
画像を検索するので、APIへアクセスするためのURLは
https://api.datamarket.azure.com/Bing/Search/Image
となります。クエリパラメータは、検索するワードをQueryパラメータに指定し、レスポンスのフォーマットを指定する$formatパラメタ-にJSONを指定します。
URLにアクセスするにはベーシック認証で接続します。
r = requests.get(bing_url, params=payload, auth=('', MS_ACCTKEY))
Bing API Migration Guide にあるように、user-nameを入力無しとし、パスワードにアカウントキーを指定します。ただ、よくわからないんですが、user-nameとパスワードの両方にアカウントキーを指定しても動作するみたいです。プログラムではパスワードだけにアカウントキーを指定しています。
検索した結果のレスポンスはJSON形式になっているので、画像URL(MediaURL)を抜き出して画像をダウンロードします。画像URLのファイル名の拡張子をみてJPEGファイルのみを対象とします。
また、プログラムを実行する環境がWindowsの場合、画像データを書き込むときはバイナリモードでファイルを開きます。
f = open(fname, 'wb')
こうしないとダウンロードしたJPEGデータが正常に保存できません。
プログラムで検索するワードは「大福」にしました。好きなワードに変更すれば、それなりの画像が取得できます。このプログラムはAPIの基本的な使いかたを調べるために作ったので、検索結果は50個までです。
また、APIにアクセスするときのパラメータの説明は下記にまとまっています。
Bing API Schema Guide
感心したのは、Adultというパラメータがあり、性的なレベルを指定して検索結果をフィルタリングします。Offはフィルタリングしない、Moderateは露骨な性的画像コンテンツ(画像、ビデオ)をフィルタリングし、Strictは含まないようにフィルタリングすることになっています。どこまでが露骨な性的表現になるのか、いろいろと実験してみないことにはわかりませんが…。
#coding:utf-8 import os import requests def bing_search(query): bing_url = 'https://api.datamarket.azure.com/Bing/Search/Image' MS_ACCTKEY = 'your account key' payload = { '$format': 'json', 'Query': "'"+query+"'", } r = requests.get(bing_url, params=payload, auth=('', MS_ACCTKEY)) count = 1 for item in r.json()['d']['results']: image_url = item['MediaUrl'] root,ext = os.path.splitext(image_url) if ext.lower() == '.jpg': print image_url, r = requests.get(image_url) fname = "%04d.jpg" % count f = open(fname, 'wb') f.write(r.content) f.close() print "...save", fname count += 1 if __name__ == '__main__': bing_search('大福')