株式会社グローバルゲート公式ブログ

意外と簡単!Chrome拡張機能の作り方:画像一括ダウンローダーを作ってみよう

こんにちは、株式会社グローバルゲートのモーリーです。 
 
オリーブオイルがいよいよなくなってしまったため1500円で買う羽目になってしまいました。 
高すぎる…ワ…アッ…。

…さて、気を取り直して今回の記事ではChromeの拡張機能を作ってみようと思います。 


ブラウザでChromeをお使いの方なら拡張機能を追加することでより便利に使えるということはご存知だと思います。 
便利な拡張機能はいろいろあり、私も活用しています。

そんな拡張機能の自作は難易度が高そうなイメージがありますが、実は拡張機能はJavascriptだけで書くことができ、簡易なものならファイル数個で済んでしまいます。少しの知識があれば自作することもそれほど難しくはありません。 
 
拡張機能を作れるようになれば、ブラウザ経由で行う作業の効率化を大幅にUPさせることができます。 
ぜひ挑戦してみてください。 

今回は例として開いているページの画像をすべて取得してzipファイルに圧縮し、ダウンロードする拡張機能を作ってみます。 
 そういう拡張機能は既に公開されていますが、まぁ例として…。 

1.マニフェストファイル(manifest.json)の作成

まずは拡張機能の名前や使用ファイルの定義などを行う設定ファイルであるマニフェストファイル(manifest.json)を作成します。 


  "manifest_version": 3, 
  "name": "Image Downloader", 
  "version": "1.0", 
  "permissions": [ 
    "activeTab", 
    "downloads", 
    "scripting" 
  ], 
  "host_permissions": [ 
    "<all_urls>" 
  ], 
  "background": { 
    "service_worker": "background.js" 
  }, 
  "action": {}, 
  "content_scripts": [ 
    { 
      "matches": ["<all_urls>"], 
      "js": ["jszip.min.js", "content_script.js"] 
    } 
  ] 
}

manifest.jsonの詳細はこちらをご確認ください。 

2.バックグラウンドスクリプト(background.js)の作成 

バックグラウンドスクリプトは拡張機能アイコンをクリックされたときに実行される処理です。 
メインの処理はcontent_script.jsというファイルで行うため、このファイルではクリックされたことを伝達するための処理を書きます。

let isProcessing = false; 
 
chrome.action.onClicked.addListener((tab) => { 
  if (isProcessing) return; // すでに処理中なら新しいリクエストを無視 
  isProcessing = true; 
 
  chrome.scripting.executeScript({ 
    target: { tabId: tab.id }, 
    files: ['content_script.js'] 
  }, () => { 
    chrome.tabs.sendMessage(tab.id, { action: "download_zip" }); 
  }); 
}); 
 
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { 
  if (message.action === "reset_processing") { 
    isProcessing = false; 
  } 
}); 

拡張機能と言っても一般的なJavascriptとほとんど同じです。 
通常のJavascriptに加え、chrome自体を操作するためにchromeオブジェクト配下に各種APIが用意されています。 
詳しくはこちらをご確認ください。 

3.コンテントスクリプト(content_script.js)の作成 

処理内容によってはバックグラウンドスクリプトだけで済んでしまいますが、今回は権限の都合で2つのファイルが必要です。

コンテントスクリプトでは画像の取得やzip圧縮などを行うスクリプトを書きます。

// 既に変数が定義されていないか確認 
if (!window.isDownloadInProgress) { 
  window.isDownloadInProgress = false; 

 
function getImages() { 
  const imgElements = Array.from(document.querySelectorAll('img')); 
  const imgUrls = imgElements.map(img => img.src); 
  const cssImages = Array.from(document.querySelectorAll('*')) 
    .map(element => { 
      const backgroundImage = window.getComputedStyle(element).backgroundImage; 
      const match = backgroundImage.match(/url\(["']?([^"']*)["']?\)/); 
      return match ? match[1] : null; 
    }) 
    .filter(url => url); 
 
  return [...imgUrls, ...cssImages]; 

 
function fetchImagesAndCreateZip(urls) { 
  const zip = new JSZip(); 
  const imgFolder = zip.folder("images"); 
 
  const downloadPromises = urls.map((url, index) => 
    fetch(url) 
      .then(response => response.blob()) 
      .then(blob => imgFolder.file(`image${index + 1}.jpg`, blob)) 
  ); 
 
  Promise.all(downloadPromises).then(() => { 
    zip.generateAsync({ type: "blob" }).then(content => { 
      const url = URL.createObjectURL(content); 
      const a = document.createElement("a"); 
      a.href = url; 
      a.download = "images.zip"; 
      a.click(); 
      URL.revokeObjectURL(url); 
 
      chrome.runtime.sendMessage({ action: "reset_processing" }); 
      window.isDownloadInProgress = false; 
    }); 
  }); 

 
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { 
  if (message.action === "download_zip" && !window.isDownloadInProgress) { 
    window.isDownloadInProgress = true; 
    const urls = getImages(); 
    fetchImagesAndCreateZip(urls); 
  } 
}); 
 

zip圧縮処理はJSZipというライブラリを使用しました。

最終的に1つのフォルダの中に4つのファイルを収めています。このフォルダが拡張機能の本体となります。

4.作成した拡張機能のインストール 

公開されている拡張機能と異なり、ローカルからのインストールを有効にしてインストールを行う必要があります。 

4-1.デベロッパーモードを有効にする

拡張機能の管理画面を開き、「デベロッパーモード」のスイッチをONにします。

4-2.拡張機能フォルダを選択

「パッケージ化されていない拡張機能を読み込む」をクリックするとフォルダ選択画面が開きます。
ここで作成した拡張機能関連ファイルを収めたフォルダを選択します。

拡張機能一覧に表示されれば成功です!

実行はツールバーの拡張機能アイコンをクリックします。

実行例:丸亀製麺のメニューページの写真を全部ダウンロードする

それでは実際に実行してみます。
例として、丸亀製麺に行ったときにどのうどんにするかをいつでも検討できるように、メニューのページからうどんの写真を取得してみましょう。 

実行結果

メニューページで使用している画像がすべてダウンロードできました!
すべての画像を対象としたのでアイコン的に使われている画像も含まれますが、この程度なら目視での判別も簡単でしょう。

場合によっては拡張機能のコンテントスクリプト内で何らかのフィルタ(指定サイズ以上とか画像のクラス名とか)をかけるとピンポイントでうどんの写真だけを取得することもできると思います。

ちなみに丸亀製麺で私のおすすめは親子丼です

まとめ 

今回はアイコンをクリックして処理を実行するだけでしたが、拡張機能ではタブの操作や開発者ツールでしか使えないような機能の使用、HTMLによって作成した操作パネルを表示するなど様々なことができます。 
 
ぜひチャレンジしてみてください! 

【関連記事】

ご相談・お問い合わせ

当社サービスについてのお問い合わせは下記までご連絡下さい。

お電話でのお問い合わせ

06-6121-7581 / 03-6415-8161