はじめに
- 特定のページからちょこっと情報を取得したいけど、NodeJSやPythonでがっつりやるのは大袈裟過ぎる
- 非エンジニアさん向けのスクレイピングツールを作りたいけど、相手のPCに動作環境がない
こんなときはChrome Extensionとかいかがでしょうか?
Chrome Extensionなら、Google Chrome(動作環境)とExtensionの入ったフォルダさえあれば動きます。
本記事では、Chrome Extensionで簡易的なスクレイピングを行う方法を紹介します。
コード一式はこちら。
コード
以下の順番で実装していきます。
- Chrome Extensionでポップアップを表示する
- ポップアップ内のボタンを押してバックグラウンドでタブを開く
- 開いたタブの内容を取得してポップアップ内に表示
- 表示した内容をクリップボードにコピー
用途としては「管理画面の入力に必要な情報を特定のページから取得して参照する」などを想定してます。
ブラウザアクションを追加してポップアップを有効にする
manifest.jsonで、browser_actionを有効にします。
// manifest.json
{
...
"browser_action": {
// ツールバーにエクステンションを表示する設定 + 表示するアイコンのパス
"default_icon": "icon128.png",
// ツールバーのアイコンをクリックしたときにポップアップを表示する設定
"default_popup": "popup/popup.html"
}
}
ポップアップから新しいタブをバックグラウンドで開く
ポイントは2つ
- chrome.tabs APIを使用できるように、permissionsにtabsをセットする
- タブを開いた時点でポップアップが閉じないように、chrome.tabs.createメソッドのactiveオプションにfalseを渡す
// manifest.json
{
...
// chrome.tabs.createなどのメソッドを使用できるように設定
"permissions: ["tabs"]
}
// popup.js
async function loadNewTab(url, timeoutSeconds = 5) {
return new Promise((resolve, reject) => {
let targetTabId = null
const listener = (tabId, changedProps) => {
if (tabId != targetTabId || changedProps.status != 'complete') {
return
}
chrome.tabs.onUpdated.removeListener(listener)
resolve(tabId)
}
chrome.tabs.onUpdated.addListener(listener)
// ポップアップが閉じないように、active: falseを設定する
chrome.tabs.create({ url, active: false }, (tab) => {
// 開いたtabのidをスコープの変数にセットする
targetTabId = tab.id
})
setTimeout(() => {
reject(new Error('Time out...'))
}, timeoutSeconds * 1000)
})
}
loadNewTabメソッドをpopup.htmlに設置したボタンのイベントリスナー内で呼び出します。
Promiseで包んでasyncにしていますが、普通にコールバック内で結果を受けるようにしても問題ありません。
新しく開いたタブから情報を取得してポップアップに表示する
ここでは例として、英語版Wikipediaのトップページから本日の記事のテキストを取得します。
ポイントは3つ
- permissionsに情報を取得したいURLを指定する(ホストだけでもOKのようです)
- chrome.tabs.executeScriptの第一引数にtabIdを渡すことで、非アクティブのタブでスクリプトを実行可能
- chrome.tabs.executeScriptのコールバックでスクリプトの結果を取得可能
// manifest.json
{
...
"permissions": [
"tabs",
"https://en.wikipedia.org/wiki/Main_Page"
]
// popup.js
async function parseWikipedia(tabId) {
return new Promise((resolve, reject) => {
chrome.tabs.executeScript(
tabId,
{ file: 'parser/parseWikipedia.js' },
(results) => {
if (results[0] === null) {
reject(new Error('Failed to parse wikipedia.'))
} else {
resolve(results[0])
}
}
)
})
}
// parseWikipedia.js
;(() => {
function parse() {
// Get text from "From today's featured article"
return document.querySelector('#mp-tfa p').textContent
}
try {
return parse()
} catch (e) {
console.log(e)
return null
}
})()
chrome.tabs.executeScriptに渡すスクリプトでは、結果もしくはnullを返すようにしています。
スクリプト内でキャッチできない例外が発生した場合は、results[0]にはundefinedが入るようです。
ポップアップ内に表示した結果をクリップボードにコピーする
// 結果は、<textarea id="content"></textarea>のtextContentに格納されている前提
function copyResult() {
document.querySelector('#content').select()
document.execCommand('copy')
}
終わりに
定期的に実行するほどでもないけど、たまにスクレイピングしたいみたいなときにも便利かと思います。
ちょっとスクレイピングしたいなってときも、ボタンとURL、ページ固有のスクリプトを追加するだけで済みます。是非使ってみてください!
コード一式はこちら(再掲)。