HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
English Translate 中文翻訳
LINK
BACK
 

[NEW] 2020/09/29

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法 機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法

(画像検索結果一括ダウンローダ、JavaScript言語を使って、ブラウザの開発者モードのコンソールで動かします、ググれ勝つ)

Tags: [Raspberry Pi], [電子工作], [ディープラーニング]





●利用規約(免責事項)

 本ページの内容による画像取得の方法や実施について、当方は一切の責任を負いません。
 利用者ご自身の判断と責任において利用するものとします。
 本ページの内容による画像取得を実施された場合、その時点をもって利用者は本規約に同意したものとみなします。


●機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法

 Google画像検索の検索結果のサムネイル画像の一括ダウンローダです。

 機械学習では物体の認識に「学習用の画像」が大量に必要になります。

 各所から既に学習済みのモデルも提供されていますが、自分で実験したい時に対象となる目的の学習データが無い事があります。
 かといって、自分で画像を用意するのは面倒くさい。

 と言う事で画像検索の検索結果をマルぱく、、、以下略

 JavaScript言語を使って、ブラウザの開発者モードのコンソールで動かします。

 Chromeブラウザで Goolge画像検索の画面を出した状態で、F12キーで「開発者モード」にして、「コンソール」に下記をコピペして実行します。

 最初に保存する画像ファイルのファイル名の先頭部分を入力します。

 その後は全自動で下記の動作を行ない、検索結果の全部のサムネイル画像を根こそぎ収集します。

 ・最初に、検索結果を全部認識させる為にスクロールを行ない、検索結果の最後までを表示します。
 ・その後は、全自動で画像を取得して保存します。

 ※ 最初に実行時に「複数ファイルのダウンロード」の許可のダイアログが出ます。「許可」をしてください。

 既に同じ事を行なうツールが沢山ありますが、JavaScript言語で一度は自分で作ってみたかった、と言うのが製作の動機です。

 処理の内容は、Google画像検索の HTML内の class定義を元に画像の情報をリストで取得して、ループしています。

 Google画像検索は、最初の 40件位の画像データは Base64の文字列で HTML内に埋め込まれており、それ以降は httpsの通常の httpアクセスで取得しています。

 JavaScript言語はバイナリの扱いが特殊な為に、最初のうちは保存したファイルが正しくなく、画像を表示できないバグが有って苦労しました。
 また、XMLHttpRequestによる httpアクセスでもバイナリデータの取得に癖があり、これでも苦労しました。

 JavaScript言語をメインとしたプログラマにならなくて良かったと思いました。
 (最近は Node.jsで必要なんですが、、、)

 画像1枚毎に await delay(100);で 100msのウェイトを入れていますが、これが無いと Chromeブラウザのダウンロード数制限に引っ掛かり 10個しかダウンロードしてくれません。

// Input Filename
baseFilename = window.prompt("Input SAVE Image Filename", "image_");

// 1st Scroll
await scrollToBottom("mye4qd");

// Click
document.getElementsByClassName("mye4qd")[0].click();

// 2nd Scroll
await scrollToBottom("OuJzKb");

// Google Image Search Preview Downloader
// <img class="rg_i Q4LuWd" data-src="xxxx"
// Get All element="img" class="rg_i" (NodeList)
// https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll
var imgs = document.body.querySelectorAll('img.rg_i');
for (var i = 0; i < imgs.length; ++i) {

  let imageStr = imgs[i].src;
  if (imageStr == "") continue;

  imgs[i].scrollIntoView();

  // Sleep 100ms
  await delay(100);

  // for Debug
  // console.log(imgs[i].alt);
  let image = new Image();
  image.src = imageStr;
  // document.body.appendChild(image);

  var imageContent;
  var imageType;
  var imageExt;

  if (imageStr.slice(0,6) === 'https:') {
    console.log(i +': '+ imageStr);

    // Jpeg or PNG
    imageContent = load_binary_resource(imageStr);
    imageType = 'image/jpeg';
    imageExt = "jpg";

    if (imageContent.charCodeAt(1) == 80) {
        imageType = 'image/png';
        imageExt = "png";
    }

  } else if (imageStr.slice(0,5) === 'data:') {
    // console.log(i +': '+ imageStr);

    let pos = imageStr.indexOf(';base64,');
    if (pos < 0) continue;

    let base64 = imageStr.substr(pos+8);

    // Jpeg only
    imageContent = atob(base64);
    imageType = imageStr.substring(5, pos);
    imageExt = "jpg";

  } else {
    console.log(i +': '+ imageStr);
    continue;
  }

  let imageLength = imageContent.length;
  if (imageLength == 0) continue;

  let fileName = baseFilename+('0000'+i).slice(-4)+"."+imageExt

  // Convert Pure ArrayBinary
  let buffer = new Uint8Array(imageLength);
  for (let n = 0; n < imageLength; ++n) {
      buffer[n] = imageContent.charCodeAt(n) & 0xFF; // to 8bit
  }

  // Create Auto Download
  let blob = new Blob([buffer], {type: imageType});
  let url = window.URL.createObjectURL(blob);
  let a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  a.href = url;
  a.download = fileName;
  a.click();

  console.log(i +': '+ fileName);
}

// 古いブラウザーでのバイナリデータの受信
// Receiving binary data in older browsers
// https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
function load_binary_resource(url) {
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
  // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  req.overrideMimeType('text\/plain; charset=x-user-defined');
  req.send(null);
  if (req.status != 200) return '';
  return req.responseText;
}

// Scroll to Bottom End
async function scrollToBottom(className) {
  for (var i = 0; i < 50; ++i) {
    var element = document.documentElement;
    var bottom = element.scrollHeight - element.clientHeight;
    window.scroll(0, bottom);
    // console.log(bottom);

    // End of Scroll
    if (document.getElementsByClassName(className)[0].clientHeight > 0) break;

    // Sleep 200ms
    await delay(200);
  }
}

// Sleep
function delay(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}


●終わった後に音を鳴らしたい場合はこれを実行する

 JavaScript単体で Audio+Base64で Beep音を鳴らす方法。

Base64 audio tests

var snd = new Audio("data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU2LjI1LjEwMQAAAAAAAAAAAAAA/+NAwAAAAAAAAAAAAFhpbmcAAAAPAAAAAwAAA3YAlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaW8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw////////////////////////////////////////////AAAAAExhdmYAAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAN2UrY2LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/jYMQAEvgiwl9DAAAAO1ALSi19XgYG7wIAAAJOD5R0HygIAmD5+sEHLB94gBAEP8vKAgGP/BwMf+D4Pgh/DAPg+D5//y4f///8QBhMQBgEAfB8HwfAgIAgAHAGCFAj1fYUCZyIbThYFExkefOCo8Y7JxiQ0mGVaHKwwGCtGCUkY9OCugoFQwDKqmHQiUCxRAKOh4MjJFAnTkq6QqFGavRpYUCmMxpZnGXJa0xiJcTGZb1gJjwOJDJgoUJG5QQuDAsypiumkp5TUjrOobR2liwoGBf/X1nChmipnKVtSmMNQDGitG1fT/JhR+gYdCvy36lTrxCVV8Paaz1otLndT2fZuOMp3VpatmVR3LePP/8bSQpmhQZECqWsFeJxoepX9dbfHS13/////aysppUblm//8t7p2Ez7xKD/42DE4E5z9pr/nNkRw6bhdiCAZVVSktxunhxhH//4xF+bn4//6//3jEvylMM2K9XmWSn3ah1L2MqVIjmNlJtpQux1n3ajA0ZnFSu5EpX////uGatn///////1r/pYabq0mKT//TRyTEFNRTMuOTkuNaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq/+MQxNIAAANIAcAAAKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqg==");
snd.play();


●機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法

 例として、「男性」「女性」の画像を検索してみました。

・機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法


機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法


機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 F12キーで「開発者モード」にして、「コンソール」を開きます。
 警告
 このコンソールを使用すると、Self-XSS と呼ばれる手法を使ってあなたになりすました攻撃者によって個人情報が騙し取られる可能性があります。よくわからないコードは、入力したり貼り付けたりしないでください。
 上記の一括画像取得の JavaScriptのコードは上記の様な危険な処理は入っていません。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 右上の「…」をクリックで、コンソールの形状を変更できます。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 コンソールの形状を「下部」に変更した場合。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 画像の上で右クリックで「検証」を選びます。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 画像の imgタグの属性情報を確認出来ます。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 同様に画面下部の「画像をもっと表示」ボタンの属性情報を調べます。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 同様に画面下部の「未読はありません」表示の属性情報を調べます。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 コンソールに「一括画像取得」の JavaScriptのコードをコピペします。

・機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 保存する画像のファイル名の先頭部分を入力します。

・機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 ※ 最初に実行時に「複数ファイルのダウンロード」の許可のダイアログが出ます。「許可」をしてください。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法


機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 自動的に画像を取得して保存します。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 自動的に画像を取得して保存します。

機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法
 結果的に 760枚の画像を保存しました(0から始まるので 759で 760枚)


●機械学習用に画像検索の結果一覧のサムネイル画像を JavaScriptで全自動で一括で取得する方法の補足

 imgタグが既に画像を読み込んでいるから、そこから画像のバイナリデータを取得すれば、わざわざ XMLHttpRequestを使って URLでのダウンロード処理が不要になってハッピーと思い、下記のコードを作成しましたが オリジン間リソース共有 CORS制限で動きませんでした。
  var img = imgs[i]
  // img.crossOrigin = "Anonymous";

  var canvas = document.createElement('canvas')
  canvas.width = img.naturalWidth
  canvas.height = img.naturalHeight

  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0);

  // VM3193:1 Uncaught DOMException
  // Failed to execute 'getImageData' on 'CanvasRenderingContext2D'
  // The canvas has been tainted by cross-origin data.
  // at <anonymous>:1:20 (anonymous) @ VM3193:1
  var buffer = ctx.getImageData(0, 0, canvas.width, canvas.height);

  // VM3202:1 Uncaught DOMException
  // Failed to execute 'toDataURL' on 'HTMLCanvasElement'
  // Tainted canvases may not be exported.
  // at <anonymous>:1:24 (anonymous) @ VM3202:1
  var dataUri = canvas.toDataURL();


●一般的には Python言語で動く Beautiful Soupを使うらしい

 Beautiful Soupは bs3や bs4と略されたり、Soupとも言われたりもします。
 (こんな言い方をサラッとされても、名称を知らんとわからんがな)

 スクレイピングやクロールの単語と一緒にググルと検索できます。

Beautiful Soup We called him Tortoise because he taught us .
beautifulsoup4 - PyPI

beautifulsoup4 4.9.3
pip install beautifulsoup4

※ beautifulsoup3は既に過去の物



Tags: [Raspberry Pi], [電子工作], [ディープラーニング]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

マイクロソフトの提供する無料の機械学習アプリ Lobeで遊んでみる
マイクロソフトの提供する無料の機械学習アプリ Lobeで遊んでみる

  機械学習アプリ Lobeで「ごちうさ」のキャラ画像を機械学習してカメラで認識するかテストしてみるんゴ!



[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2020 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/software/image_downloader_search_engine_deep_learning/