技術メモ

後で同じ状況が起こった時に思い出せるように技術的なちょっとしたことをメモする。ベストな解ではない。



Web上から画像を収集(スクレイピング)するスクリプトを書いた


機械学習などで画像を収集したいことがある。
学習用の画像は、買ったり、自分で撮影したり、公開されているデータセットを使ったり、インターネットから拾ってきたり、と様々な方法で入手可能である。
今回はインターネットから画像を拾ってくるスクリプトを書いたのでそれの記録を残す。
なお、ここで示すのスクリプトや規約は記事投稿時点での内容となっている。そこからWebサイトの仕様や規約が変わっていなければそのまま使えるはずである。(仕様は結構変わるのでその都度変更が必要になる。)





 

概要

画像検索サービスにはGoogle, Bing, Twitterなど様々なものがあるが、規約的にだめだったり、検索ページがJSなどで動的に生成されて技術的にスクレイピングが難しかったり、APIの利用制限があったりするサイトが多い。
今回は、規約上問題なさそう(駄目とは明記されていない)でかつ簡単にスクレイピングが可能そうなYahoo!検索(画像)の簡易版を使った。
キーワードをYahoo!画像検索に渡し、HTMLをお馴染みのRubyのNokogiriを使ってパースしてimgのsrcのURLを取得し、画像をダウンロードして保存する。
Yahoo!画像検索の簡易版を用いる理由は表示がページネーションしてあり、URLの変更だけで次の画像を読み込むことができるからである。





 
Yahoo!画像検索の簡易版のURLの構造は次のようになっている。
https://search.yahoo.co.jp/image/search?p=#{keyword}&rkf=1&oq=&dim=&ctype=photo&imc=&ei=UTF-8&xargs=7&b=#{number}
#{keyword}には検索ワード、#{number}にはページ先頭の画像のインデックスが入っていると思われる。
Yahoo!画像検索の簡易版では1ページに20枚の画像が出てくるので、#{number}は20n+1の値を入れる。
例えば、”メタルスライム”の最初の1ページのURLは”https://search.yahoo.co.jp/image/search?p=メタルスライム&rkf=1&oq=&dim=&ctype=photo&imc=&ei=UTF-8&xargs=7&b=1“となる。




 
ここから、Webブラウザの開発ツールを使って、画像のURLを取得する。
Nokogiriの使用方法やWeb開発ツールの使い方・見方はここを参照。
これによって、idがgridlist(#gridlist)のimgタグのsrc属性に画像のURLがあることがわかる。

あとはこのページ全体の#gridlist内の画像のURLを取得し、そこからダウンロードし、次のページ(URLの#{number}を20増やす)でもそれを繰り返すだけで、大量の画像が手に入る。





 

コード

コードのサンプルを以下に示す。
なおこのサンプルを動かすためにはRubyとそのgemであるNokogiriが必要である。

5-9行目はキーワードとページを渡すと検索用のURLを生成する。
11-19行目は検索用URLから#gridlistのimgタグのsrc属性を返す。画像が取得できないときにはnilを返す。
21-37行目は画像のURLの配列を受け取りそれを順に開いてダウンロードする。その際、ファイル名は連番でつけている。なお、ここでは拡張子を強制的にjpgにしているがこれはダウンロードされる画像の形式がわからないので仮でつけている。
39-65行目はこれらの一連の流れをパージごとに繰り返す。最初に指定されたパスのディレクトリがなければ作成し、1ページ目から画像をダウンロードしていく。これを指定された画像枚数を超えるまで繰り返す。各ページ取得の間には0.5秒のスリープを入れて相手サーバーへの負荷を少し減らしている。
67-77行目がコマンドライン引数からキーワードや保存先パス、目標枚数などを取得して実際に処理を回している。





 
なお、このコードは以下のボタンからダウンロードできる。





 
ソースコードを見れば使い方はわかると思うが、ruby crawler.rb キーワード 保存先ディレクトリ名 目標枚数で実行できる。
例えば、メタルスライムをslimeフォルダに50枚以上集めたいときには、ruby crawler.rb メタルスライム slime 50となる。
フォルダ名はなければ自動的に生成される。目標枚数は1ページ単位で超えたかどうかをチェックするため、最大で+19枚ほど保存される場合がある。





 

実行例

メタルスライムをslimeフォルダに30枚以上集めたいときのコマンド(ruby crawler.rb メタルスライム slime 30)の実行例を見てみる。

きちんと画像が保存されている事がわかる。





 

注意

このスクリプトはきちんと節度を守って利用してほしい(本来はAPIなどを利用するべきである)。
また、サイトの仕様が変わるとそのままでは利用できないので、何かしらの手を加える必要があるので注意。
Yahoo!の規約は変わるかもしれないのでチェックしてから利用するべし。
検索の精度はYahooに依存するが、ぜんぜん違う画像が出てくる可能性も十分にあるので保存される画像を利用する前にチェックするべし。



タグ: ,
投稿日: 2018年8月13日





コメントを残す

回答をお約束することは出来ませんので予めご了承ください。
コメントは承認されると表示されるようになります。
コメントを送信する前に「私はロボットではありません」にチェックを入れて下さい。