ねこじゃすり
猫を魅了する魔法の装備品!
【最新機種】GoPro hero11 Black
最新機種でVlogの思い出を撮影しよう!
[ノースフェイス] THE NORTH FACE メンズ アウター マウンテンライトジャケット
防水暴風で耐久性抜群なので旅行で大活躍です!
レッドブル エナジードリンク 250ml×24本
翼を授けよう!
モンスターエナジー 355ml×24本 [エナジードリンク]
脳を活性化させるにはこれ!
BANDAI SPIRITS ULTIMAGEAR 遊戯王 千年パズル 1/1スケール
もう一人の僕を呼び覚ませ!!
サンディスク microSD 128GB
スマホからSwitchまで使える大容量MicroSDカード!
スポンサーリンク
目次
大量のURLの画面キャプチャを自動化したい
もはやキャプチャ保存は人間のやる作業ではない
サイト開発等をしている場合、開発中の各画面のキャプチャを保存したいというケースがありますよね。
しかし、人力でブラウザで全てのページを開いてキャプチャツールを使って保存、、、なんて作業をするのはとても骨が折れます。
そんな時は、NightmareJSを使って自動化しちゃいましょう!
nightmareとは?
NightmareJSとは、スクレイピングなどを行う際に多く利用されるPhantomJSという有名なヘッドレスブラウザをさらに扱いやすくしたラッパーツールです。
A high-level browser automation library.
Nightmare
PhantomJSを使うとこう書いていた部分が、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
phantom.create(function (ph) { ph.createPage(function (page) { page.open('http://yahoo.com', function (status) { page.evaluate(function () { var el = document.querySelector('input[title="Search"]'); el.value = 'github nightmare'; }, function (result) { page.evaluate(function () { var el = document.querySelector('.searchsubmit'); var event = document.createEvent('MouseEvent'); event.initEvent('click', true, false); el.dispatchEvent(event); }, function (result) { ph.exit(); }); }); }); }); }); |
こうなる。
1 2 3 4 |
yield Nightmare() .goto('http://yahoo.com') .type('input[title="Search"]', 'github nightmare') .click('.searchsubmit'); |
神かよ!!!
って事で早速使ってみました。
手順
phantomjsのインストール
nightmarejsはPhantomejsに依存しているのでまずはそちらをインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
yarn add v1.17.3 warning package.json: No license field warning No license field [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 Building fresh packages... success Saved lockfile. warning No license field success Saved 91 new dependencies. info Direct dependencies └─ phantomjs@2.1.7 info All dependencies ├─ ansi-styles@2.2.1 ├─ asn1@0.2.4 ├─ async@2.6.3 ├─ aws-sign2@0.6.0 ├─ balanced-match@1.0.0 ├─ bcrypt-pbkdf@1.0.2 ├─ bl@1.0.3 ├─ brace-expansion@1.1.11 ├─ caseless@0.11.0 ├─ chalk@1.1.3 ├─ combined-stream@1.0.8 ├─ commander@2.20.0 ├─ concat-map@0.0.1 ├─ concat-stream@1.5.0 ├─ core-util-is@1.0.2 ├─ cryptiles@2.0.5 ├─ dashdash@1.14.1 ├─ debug@0.7.4 ├─ delayed-stream@1.0.0 ├─ ecc-jsbn@0.1.2 ├─ escape-string-regexp@1.0.5 ├─ extend@3.0.2 ├─ extract-zip@1.5.0 ├─ extsprintf@1.3.0 ├─ fd-slicer@1.0.1 ├─ forever-agent@0.6.1 ├─ form-data@1.0.1 ├─ fs-extra@0.26.7 ├─ fs.realpath@1.0.0 ├─ generate-function@2.3.1 ├─ generate-object-property@1.2.0 ├─ getpass@0.1.7 ├─ glob@7.1.4 ├─ graceful-fs@4.2.2 ├─ har-validator@2.0.6 ├─ has-ansi@2.0.0 ├─ hasha@2.2.0 ├─ hawk@3.1.3 ├─ http-signature@1.1.1 ├─ inflight@1.0.6 ├─ inherits@2.0.4 ├─ is-my-ip-valid@1.0.0 ├─ is-my-json-valid@2.20.0 ├─ is-property@1.0.2 ├─ is-stream@1.1.0 ├─ is-typedarray@1.0.0 ├─ isarray@1.0.0 ├─ isexe@2.0.0 ├─ isstream@0.1.2 ├─ json-schema@0.2.3 ├─ json-stringify-safe@5.0.1 ├─ jsonfile@2.4.0 ├─ jsonpointer@4.0.1 ├─ jsprim@1.4.1 ├─ kew@0.7.0 ├─ klaw@1.3.1 ├─ lodash@4.17.15 ├─ mime-db@1.40.0 ├─ mime-types@2.1.24 ├─ minimatch@3.0.4 ├─ minimist@0.0.8 ├─ mkdirp@0.5.0 ├─ node-uuid@1.4.8 ├─ oauth-sign@0.8.2 ├─ pend@1.2.0 ├─ phantomjs@2.1.7 ├─ pinkie@2.0.4 ├─ process-nextick-args@1.0.7 ├─ progress@1.1.8 ├─ qs@5.2.1 ├─ readable-stream@2.0.6 ├─ request-progress@2.0.1 ├─ request@2.67.0 ├─ rimraf@2.7.1 ├─ safer-buffer@2.1.2 ├─ sntp@1.0.9 ├─ sshpk@1.16.1 ├─ string_decoder@0.10.31 ├─ stringstream@0.0.6 ├─ strip-ansi@3.0.1 ├─ supports-color@2.0.0 ├─ throttleit@1.0.0 ├─ tough-cookie@2.2.2 ├─ tunnel-agent@0.4.3 ├─ tweetnacl@0.14.5 ├─ typedarray@0.0.6 ├─ util-deprecate@1.0.2 ├─ verror@1.10.0 ├─ which@1.2.14 ├─ xtend@4.0.2 └─ yauzl@2.4.1 ✨ Done in 36.27s. |
NightmareJSのインストール
次にNightmareJSをインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
yarn add v1.17.3 warning package.json: No license field warning No license field [1/4] 🔍 Resolving packages... warning nightmare > electron > electron-download > nugget > progress-stream > through2 > xtend > object-keys@0.4.0: [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 Building fresh packages... success Saved lockfile. warning No license field success Saved 85 new dependencies. info Direct dependencies └─ nightmare@3.0.2 info All dependencies ├─ @types/node@8.10.53 ├─ ajv@6.10.2 ├─ array-find-index@1.0.2 ├─ asynckit@0.4.0 ├─ aws4@1.8.0 ├─ buffer-from@1.1.1 ├─ camelcase-keys@2.1.0 ├─ camelcase@2.1.1 ├─ clone@1.0.4 ├─ code-point-at@1.1.0 ├─ commander@1.0.4 ├─ currently-unhandled@0.4.1 ├─ decamelize@1.2.0 ├─ deep-defaults@1.0.5 ├─ deep-extend@0.6.0 ├─ defaults@1.0.3 ├─ electron-download@3.3.0 ├─ electron@2.0.18 ├─ enqueue@1.0.2 ├─ error-ex@1.3.2 ├─ es6-promise@4.2.8 ├─ fast-deep-equal@2.0.1 ├─ fast-json-stable-stringify@2.0.0 ├─ find-up@1.1.2 ├─ function-source@0.1.0 ├─ har-schema@2.0.0 ├─ home-path@1.0.6 ├─ hosted-git-info@2.8.4 ├─ indent-string@2.1.0 ├─ ini@1.3.5 ├─ is-arrayish@0.2.1 ├─ is-finite@1.0.2 ├─ is-fullwidth-code-point@1.0.0 ├─ is-utf8@0.2.1 ├─ jsesc@0.5.0 ├─ json-schema-traverse@0.4.1 ├─ keypress@0.1.0 ├─ load-json-file@1.1.0 ├─ loud-rejection@1.6.0 ├─ map-obj@1.0.1 ├─ meow@3.7.0 ├─ minimist@1.2.0 ├─ minstache@1.2.0 ├─ mkdirp@0.5.1 ├─ ms@2.0.0 ├─ multiline@1.0.2 ├─ nightmare@3.0.2 ├─ normalize-package-data@2.5.0 ├─ nugget@2.0.1 ├─ object-assign@4.1.1 ├─ object-keys@0.4.0 ├─ parse-json@2.2.0 ├─ path-exists@2.1.0 ├─ path-parse@1.0.6 ├─ path-type@1.1.0 ├─ performance-now@2.1.0 ├─ pretty-bytes@1.0.4 ├─ progress-stream@1.2.0 ├─ psl@1.4.0 ├─ punycode@1.4.1 ├─ rc@1.2.8 ├─ read-pkg-up@1.0.1 ├─ read-pkg@1.1.0 ├─ redent@1.0.0 ├─ repeating@2.0.1 ├─ resolve@1.12.0 ├─ safe-buffer@5.1.2 ├─ semver@5.7.1 ├─ signal-exit@3.0.2 ├─ single-line-log@1.1.2 ├─ sliced@1.0.1 ├─ spdx-correct@3.1.0 ├─ spdx-exceptions@2.2.0 ├─ speedometer@0.1.4 ├─ split2@2.2.0 ├─ string-width@1.0.2 ├─ strip-bom@2.0.0 ├─ strip-indent@1.0.1 ├─ strip-json-comments@2.0.1 ├─ sumchecker@1.3.1 ├─ through2@2.0.5 ├─ trim-newlines@1.0.0 ├─ uri-js@4.2.2 ├─ uuid@3.3.3 └─ validate-npm-package-license@3.0.4 ✨ Done in 93.50s. |
スクリーンショットを保存
まずは試しに、Googleで検索した結果をキャプチャ保存するスクリプトを書いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
const Nightmare = require('nightmare') const nightmare = Nightmare({ show: true})// ブラウザの設定 nightmare .goto('https://google.com') // 表示するURL .type('input[type=text]', 'blogenist') //タイピング対象のセレクタと入力値 .click('input[name=btnK]')// クリック対象のセレクタ .wait('#resultStats') // 表示されるまで待つセレクタ .screenshot("./sample.png") // キャプチャの保存設定 .end() // 終了 .catch(error => { console.error('Search failed:', error) }) |
また、yarn
で簡単に起動するためにpackage.json
のscripts
に以下の起動スクリプトを追記しておきます。
1 2 3 4 5 6 7 8 9 10 |
{ "scripts": { "capture": "node ./capture.js" // 追加 }, "devDependencies": { "nightmare": "^3.0.2", "phantomjs": "^2.1.7" }, "dependencies": {} } |
確認
では、実際にyarn capture
で起動してみましょう。
正しく検索操作とキャプチャ保存も出来ていますね♪
複数画面を自動キャプチャ保存
では、応用として複数画面のキャプチャを自動で保存してみましょう。
今回は、config.json
というファイルにキャプチャしたいページを管理し、ループ処理で自動保存する形式にしようと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "pages": [ { "name": "ページ1", "url": "https://blogenist.jp/2019/09/09/9157/" }, { "name": "ページ2", "url": "https://blogenist.jp/2019/09/08/9128/" }, { "name": "ページ3", "url": "https://blogenist.jp/2019/09/06/9121/" } ] } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
const Nightmare = require('nightmare') const fs = require('fs'); const config = require('./config.json'); config.pages.forEach((page) => { const nightmare = Nightmare({ show: false,width: 1920}) const dist = `./dist/${page.name}/`; const fileName = `${page.name}.png`; if (!fs.existsSync(dist)) { fs.mkdirSync(dist); } nightmare .goto(page.url) .wait(1000) .screenshot(`${dist}/${fileName}`) .end() // 終了 .catch(error => { console.error('Search failed:', error) }) }); |
レスポンシブも対応
さらに以下のようにデバイス情報を追記し、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
{ "pages": [ { "name": "ページ1", "url": "https://blogenist.jp/2019/09/09/9157/" }, { "name": "ページ2", "url": "https://blogenist.jp/2019/09/08/9128/" }, { "name": "ページ3", "url": "https://blogenist.jp/2019/09/06/9121/" } ], "devices": [ { "name": "PC", "width": 1920, "height": 1080 }, { "name": "Tablet", "width": 768, "height": 1024 } ] } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
const Nightmare = require('nightmare') const fs = require('fs'); const config = require('./config.json'); config.devices.forEach((device) => { config.pages.forEach((page) => { const nightmare = Nightmare({ show: false,width: device.width, height: device.height}) const dist = `./dist/${page.name}/`; const fileName = `${device.name}-${page.name}.png`; if (!fs.existsSync(dist)) { fs.mkdirSync(dist); } nightmare .goto(page.url) .wait(1000) .screenshot(`${dist}/${fileName}`) .end() }) }); }); |
ネストループする事で一気に2端末分のレスポンシブデザインの確認をするためのキャプチャも取れてしまいます・・・!
かなり便利です!!!
スクロール領域のキャプチャ
次は縦スクロールが発生する画面のキャプチャを撮ってみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
const Nightmare = require('nightmare') const fs = require('fs'); const config = require('./config.json'); config.pages.forEach((page) => { const nightmare = Nightmare({ show: false,width: device.width, height: device.height}) const dist = `./dist/${page.name}/`; const fileName = `${device.name}-${page.name}.png`; if (!fs.existsSync(dist)) { fs.mkdirSync(dist); } nightmare .goto(page.url) .wait(1000) .evaluate(() => { return { width: document.body.scrollWidth, height: document.body.scrollHeight }; }) .then(({ width, height }) => { nightmare.viewport(width, height); }) .then(() => { nightmare.screenshot(`${dist}/${fileName}`) .end() .catch(error => { console.error('Search failed:', error) }) }) }); |
確認
正常にスクロールが発生する画面でも全体のキャプチャが取れました。
終わりに
以上のように、簡単に画面キャプチャを撮る事が出来ました。
たくさんの画面キャプチャを取らないといけない場合は、あらかじめ導入しておくととても便利ですので是非試して見てください♪