Yahoo、Bing、Googleでの画像収集事情まとめ

## やりたいこと

機械学習用の画像が大量に必要になったときに、画像検索エンジンのAPIを使ったりスクレイピングすることを考えるわけですが、とにかくAPI仕様が変わったりネットに落ちてるコードが動かなかったりで地味にツライ作業になりがちです。

今回やりたいことは

1. 機械学習用の画像を数千枚オーダーで集めたい
2. とにかく簡単にやりたい。こんなことに時間を使いたくない。
3. 画像が集まりさえすれば検索エンジンはどこでも良い
4. 楽に終わるのであれば多少課金しても良い（有料APIを使っても良い）

特に2が大切。我々が本当にやりたいのは機械学習であって「画像収集」ではない。

## 一応ググってみる

課金しても良いのですが、お金をかけずに簡単に出来るならそれに越したことはないです。

というわけで、"google image scraper" あたりで適当にググって、出てきたgithubのコードをcloneして動かしみるんですが如何せん簡単には動きません。Seleniumなどでページ遷移して画像を掘っていくようなコードもありましたが簡単には動いてくれない。 そしてそれを直すような気力も無い...

大人しく検索エンジンのAPIを使ってやる方法に変更します。とにかく楽にやりたいんや...

## Yahoo, Bing, GoogleのAPIを調べる

これまでまともに画像検索用のAPIを調べたことがなかったので、勝手なイメージで「まぁ公式にサービスされている画像検索API使えば数千枚くらい簡単にあつまるんやろ。もしかしたら課金必要かもだけど、どうせ＄300クーポンあげます的なやつで実質無料でできるんでしょ？」と思ってました。

が、現実は甘くなかった。APIを使っても依然として問題な部分もありました。そもそもYahooはAPIサービスを終了していたり... そのへんを（個人的に試した範囲内で）まとめたいと思います。

## 実際にやってみる

とにかく「楽に画像を集める」ことが目的です。

公開されているコードがあっても大幅に修正する必要などがあればそれは捨てて次の方法に移るというスタイル。  
比較を容易にするため、検索単語は『猫』（日本語）に限定して実際に何枚取得できたかを記録します。


### Yahooからの画像取得

Yahooはすでに画像クロール用のAPIサービスの提供を終了しているのでスクレイピングするしか方法がないようです。  
Yahooからの画像取得には[karaageさんのブログのコード](http://karaage.hatenadiary.jp/entry/2017/08/23/073000)を使わせていただきました。修正しなくても動くので非常に有り難いです。スクレイピングなのでAPI用のアカウント登録なども特に必要もなく楽ちん。

**Yahooの問題点**

* 取得できる画像がMaxで60枚（1スクロール分だけ）

参考にしたコードはSeleniumなどのページ遷移機能がないので、「次の画像を表示」的な次ページの読み込みができないので1ページの目の画像取得が終わると止まるっぽいです。取得はお手軽ですが、さすがに目標枚数を集めるには無理がありそうです。

### Bingからの画像取得

Microsoftの検索エンジン"Bing"では有料で画像取得用のAPIを提供しています。  
アカウント作成時に\$200のクーポン（ただしアカウント作成から30日間で消滅）を貰えるので実質無料で利用できます。有料では1,000トランザクションごとに\$3（1トランザクションで最大150枚画像取得可能）の課金が発生します。値段の詳細は[こちら](https://azure.microsoft.com/ja-jp/pricing/details/cognitive-services/search-api/web/)

Microsoftは最近サービスを「Cognitive ◯◯」に統一しようとしているようなので、この画像検索APIの利用にもそれらのサービスへのアカウント登録が必要になります。少し面倒ですが仕方なし。

**Bing APIの問題点**

* 1キーワード当たりの取得可能枚数は800枚前後でストップする
* Googleと比較して、ニッチな検索キーワードに紐づく画像が少ない印象（これは気のせいかもしれないですが。）

さすがAPIなので比較的多量の画像を一度に取得することができます。しかし自分の実行環境下では700~900枚ほど画像取得したところでAPIからのレスポンスが途絶えてしまいました。しかし「猫」と検索して出てくる画像はもっと多いと思われるので700~900枚ほどで終了するのはおかしい気がします。同様の現象を他の方も指摘しているのでAPI的な制限であると思われます。

また、今回自分はインターネット上にあまり画像が落ちていなさそうなニッチなキーワードを画像検索しているのですが、Googleで同じキーワードを検索したときの画像結果が、bingよりも自分が求めている画像が多いように見えました。多少思い込みな気もしますが、BingとGoogleでは収集している画像の質と量がやはり異なるのかもしれません。

### Googleからの画像取得

Bingよりも目的の画像が多めに取得できそうだったのでGoogleのAPIも試してみることにしました。結論から言うとGoogleの画像検索API(google custom search api)が最も扱いも面倒で結果も残念なものでした。

**Google APIの問題点**

* 1queryで最大画像10枚が取得可能であり、100query/dayまで無料で利用できます。つまり、一日1,000枚分の画像が無料で取得できることになります。（その後、1,000query単位で＄5課金が発生）
* しかし、最大の問題は「1キーワード当たり取得できる画像枚数が最大で100枚」であること。
	* 同じキーワードについて101枚目以降の画像の取得はAPIから400番エラーが返ってきます。この問題（仕様？）は数年前から指摘されていますが未だに改善されていないようです。


## まとめ

以上の内容を表にまとめると、

|  | Yahoo | Bing (Microsoft) | Google|
|:------------|:-----------|:------------|:------------|
|サービス名称|-|[Bing Image Search API](https://azure.microsoft.com/ja-jp/services/cognitive-services/bing-image-search-api/)|[Google Custom Search API](https://developers.google.com/custom-search/json-api/v1/overview)|
| scraping or API | scraping (APIは終了)|API|API|
|アカウント登録|不要|必要|必要|
|API実行に必要なkeyなど|なし|API key|API key と カスタム検索エンジンID|
|無料枠|（スクレイピングなので¥0）|アカウント登録から30日間だけ使える$200の無料クーポンが貰える|100query/dayまで無料（1queryで最大10枚取得可能）|
|有料課金|（スクレイピングなので¥0）|1,000トランザクション/$3（1トランザクションで最大150枚取得可能）|1,000query/$5|
|1キーワードに対する"実質"取得可能枚数|ページ遷移できるscraperでない場合は60枚|（原因不明のAPI挙動により）700~900枚ほど|（APIの仕様により）最大100枚|
|実際に「猫」を検索して得られた枚数|60枚|824枚|92枚|
|参考コード（ページ）|[karaageさんのブログのコード](http://karaage.hatenadiary.jp/entry/2017/08/23/073000)|[Bingの画像検索APIを使って画像を大量に収集する](https://qiita.com/ysdyt/items/49e99416079546b65dfc)|[Googleの画像検索APIを使って画像を大量に収集する](https://qiita.com/ysdyt/items/02a9e6b4e70f26385abc)|


## 「画像収集」についての結論

Q.「機械学習用の画像を1000枚以上集めたいんだけど楽な方法ない？」

A.「APIならBing一択。でも1000枚以上取得したいならSeleniumなどを使ってページを自動ロードしていくタイプのscraperを作る（or探す）」

になるのかな...   

画像データセット作りは一夜にしてならず。ツライ。

## リンク

* [スクレイピング初心者がpythonでかわいい猫ちゃん画像をコマンド一発でネットから収集してみた](http://karaage.hatenadiary.jp/entry/2017/08/23/073000)
* [Bingの画像検索APIを使って画像を大量に収集する](https://qiita.com/ysdyt/items/49e99416079546b65dfc)
* [Googleの画像検索APIを使って画像を大量に収集する](https://qiita.com/ysdyt/items/02a9e6b4e70f26385abc)
* [ysdyt/image_collectors - Github](https://github.com/ysdyt/image_collectors)