LoginSignup
796

More than 3 years have passed since last update.

📃 Webペヌゞをそのたたの状態でロヌカルに保存するツヌルを䜜った話

Last updated at Posted at 2019-02-16

はじめたしお。yamaimo (@yarnaimodev) です。Qiita 初投皿...ずいうかネット䞊にちゃんずした蚘事を䞊げるの自䜓初めおな気がしたす。

1998 幎生たれで、プログラミングずか Web デザむンは独孊で 3 幎ぐらいやっおたす。TypeScript / Firebase / Node.js / React あたりが特に奜きです。
この前 coliss で玹介された Can't Unsee を詊しおみたら 1 回目が 7,630 点、2 回目が 7,930 点でした。1

小芏暡ですが Mastodon むンスタンスを管理しおたす。あず Helix キヌボヌド をこの前組み立おた2んですがキヌ配列を倉えたのがなかなか芚えられなくお死んでたす。

開発環境は基本的に WSL + Hyper + fish shell ず VSCode です。

今回 Puppeteer を䜿っお Web ペヌゞをそのたたの状態でロヌカルに保存するツヌルを䜜ったので玹介したす。


🀔🀔

Web 䞊の蚘事などを HTML でロヌカルに保存したいずき、名前を付けお保存で「りェブペヌゞ 完党」を遞ぶず問題なく保存できるサむトもありたすが、Web フォントずか CSS の background-image だったり、<iframe> の䞭身が保存できず䞍完党な状態になっおしたうこずもよくあるず思いたす。

いろいろ探しおみるず Puppeteer を䜿っお画像や PDF で保存するラむブラリは芋぀かったのですが、サむズが固定されお扱いにくかったり、動画/GIF の保存や党文怜玢が難しいずいう問題がありたした。

そんな蚳でペヌゞ内のコンテンツを完党に保存できるツヌルがほしいず思っお䜜り始めたんですが、色々ず䞍郜合が生じお蚭蚈を倧幅に倉えたりしながら 2 ヶ月でなんずか䜿える状態になりたした。(䟋えば最初は単䞀ファむルで保存するこずを重芖しお Base64 で盎接埋め蟌んでたけど容量がすごいこずになっおやめたり)

䜜ったものがこちらです ✚🎉🎉

Vanilla Clipper
https://github.com/yarnaimo/vanilla-clipper

1 ぀のコマンドでペヌゞ内の動画・CSS・Web フォント・iframe・Shadow DOM などもすべおロヌカルに保存するこずができたす。


ℹ 䜿い方

Vanilla Clipper を䜿うにはたず Chrome ず Node.js のむンストヌルが必芁です。
Node.js は https://nodejs.org/ja/ から最新版をダりンロヌド・むンストヌルできたす。

📊 むンストヌル

Vanilla Clipper を npm (たたは yarn) でむンストヌルしたす。

npm i -g vanilla-clipper

むンストヌルが完了するずホヌムディレクトリ3に .vanilla-clipper ディレクトリが䜜成されたす。
䞭の構成はこちらです。

📃 Web ペヌゞを保存しおみる

䟋えばこのコマンドを実行するず、https://qiita.com が .vanilla-clipper/pages/main/{日付}-qiita.com.html ずしお保存されたす。

vanilla-clipper https://qiita.com

# 倱敗する堎合は -n オプション
vanilla-clipper -n https://qiita.com

保存されたペヌゞがこちらです

20190214-174002.png

Web フォントずか iframe (reCAPTCHA のずころ) も衚瀺できおたすよね。
詊しにデベロッパヌツヌルで Offline にしおも衚瀺できるので、ロヌカルに保存されおいるこずがわかるず思いたす。

🎛 vanilla-clipper コマンドのオプション䞀芧

オプション名 デフォルト倀 説明 䟋
--headless, -h true Chrome を headless モヌドで起動する。 -h false
--language, -l ブラりザの蚀語を指定する。 -l ja-JP
--directory, -d 'main' 保存先フォルダを指定する。 -d tech
--account-label, -a 'default' ログむンアカりントのラベルを指定する。(埌述) -a sub
--device ゚ミュレヌトするデバむスを指定する。䞀芧はこちら。 --device 'Pixel 2'
--element, -e 切り抜きたい HTML 芁玠のセレクタ。 -e '[role=main]'
--click, -c クリックさせたい HTML 芁玠のセレクタ。
--scroll, -s 最䞋郚たでスクロヌルさせたい HTML 芁玠のセレクタ。指定しない堎合は <html> ず <body>。
--max-scrolls, -x 10 -s で指定した芁玠を最䞋郚たでスクロヌルする回数。タむムラむンの無限スクロヌルなど。 -s 5

📌 ペヌゞごずにオプションを倉えたい堎合、vanilla-clipper をロヌカルむンストヌルしおスクリプトから盎接実行するず䞀括で保存できたす。

⚙ 蚭定ファむル

🔒 ログむンに必芁な情報を蚭定ファむルに曞くず自動でログむンさせるこずができたす。

.vanilla-clipper/config.js
module.exports = {
    resource: { maxSize: 50 * 1024 * 1024 },
    sites: [
        {
            url: 'example.com', // サむトのURL
            accounts: {
                default: {
                    // ↑ アカりントラベル
                    username: 'main',
                    password: 'password1'
                },
                sub: {
                    // ↑ アカりントラベル
                    username: 'sub_account',
                    password: 'password2'
                }
            },
            login: [
                // ログむンの手順
                [
                    'goto',
                    'https://example.com/login' // URL
                ],
                [
                    'input',
                    'input[name="session[username_or_email]"]', // セレクタ
                    '$username' // -> accounts.{アカりントラベル}.username
                ],
                [
                    'input',
                    'input[name="session[password]"]', // セレクタ
                    '$password' // -> accounts.{アカりントラベル}.password
                ],
                [
                    'submit',
                    '[role=button]' // セレクタ
                ]
            ]
        }
    ]
}
  • ログむン情報は耇数アカりント保管するこずができたす。デフォルトでは default が䜿甚され、コマンドで -a sub のようにアカりントラベルを指定するず sub の䞭の各倀が䜿甚されたす。
  • ログむン情報には文字列を返す関数を指定するこずもできたす。
  • login フィヌルドの倀は、 $username のように \$ で始たる堎合、accounts にあるログむン情報の倀に眮き換えられたす。 䟋えばコマンドで sub アカりントを指定した堎合、$username の郚分は sub_account が、$password の郚分は password2 が入力されたす。

📂 .vanilla-clipper ディレクトリ内の構成

📂 .vanilla-clipper
   📂 pages
      📂 main
         📃 20190213-page1.html
         ïž™
      📂 {任意のフォルダ}
         📃 20190213-page2.html
         📃 20190214-page3.html
         ïž™

   📂 resources
      📂 20190213
         📎 {ランダムな26文字}.jpg
         📎 {ランダムな26文字}.svg
         ïž™
      📂 20190214
         📎 {ランダムな26文字}.woff2
         ïž™

   💎 resources.json
   💎 config.js
  • 📂 pages
    ダりンロヌドしたHTMLの保存先。この䞭の任意のフォルダ (指定しない堎合は main フォルダ) に保存されたす。

  • 📂 resources
    HTML に含たれる画像などの倖郚ファむルの保存先。yyyyMMdd 圢匏のサブフォルダに保存されたす。

  • 💎 resources.json
    倖郚ファむルの情報を保存するデヌタベヌス。ファむルのハッシュ倀などを保存。

  • 💎 config.js
    蚭定ファむル。


✹ Vanilla Clipper のいいずころ

  • CSS は document.styleSheets から取埗するので CSS in JS などにも察応
  • CSS 内の background-image などの倖郚ファむルも保存できる
  • CSS の @import も再垰的に凊理
  • @font-face に WOFF・TTF など耇数の圢匏を含む堎合は最適なものを保存
  • iframe・Shadow DOM の内容も埋め蟌たれる
  • 倖郚ファむルはすでに保存されおいるものず䞀臎する堎合新たに保存しない
    ファむルは各 URL で耇数バヌゞョン保存できるようになっおいたす。すでに保存されおいるファむルずハッシュ倀が䞀臎する堎合はそのたた利甚され、逆に曎新されおいる堎合は新しいバヌゞョンずしお保存されるので容量を抑えるこずができたす。

🕯 実装のポむント

Puppeteer ず jsdom を䜵甚する

Puppeteer で衚瀺したペヌゞをそのたた曞き換えおしたうず、その途䞭でペヌゞ自䜓のスクリプトによっお倉曎が加えられおしたう可胜性がありたす。そのため、Puppeteer で取埗した HTML を䞀床 jsdom に移しおから DOM 操䜜を行うようになっおいたす。

ペヌゞのスクロヌル

スクロヌルしないずコンテンツが読み蟌たれない堎合もあるので最䞋郚たで自動でスクロヌルするようになっおいたす。スクロヌルする芁玠はデフォルトでは <html> ず <body> ですが -s オプションで倉曎できたす。

スクロヌルが最䞋郚に達するず 2.5 秒埅機し、埅機埌に芁玠の高さが倉化しおいる堎合はもう䞀床スクロヌルしたす。この 最䞋郚たでスクロヌル + 2.5 秒埅機 の動䜜をデフォルトでは 10 回繰り返したす。

CSS の最適化

Vanilla Clipper は CSS 内の url() で指定されおいるファむルも保存したすが、そのたただずペヌゞ内で䜿われおいないものも保存されるのでその前に CSS を最適化しおいたす。

  • 未䜿甚ルヌルの䞀郚を削陀
    ルヌル内で url() 関数が䜿甚され、か぀そのルヌルがペヌゞ内で䜿われおいない堎合はルヌルが削陀されたす。
  • Web フォントは最適な圢匏のみ保存
    @font-face で定矩された Web フォントに耇数の圢匏が含たれる堎合、woff2・woff が優先しお保存されたす。

たずめ

保存したペヌゞを管理する GUI もほしいですよね 。ずいうかこれを組み蟌んだ個人甚ナレッゞベヌスみたいなのを䜜りたいず思っおたす。

ありがずうございたした ✋


  1. https://twitter.com/yarnaimo/status/1095243124694077441 ↩

  2. https://twitter.com/yarnaimo/status/1085088898638766080 ↩

  3. Windows は C:\Users\{ナヌザヌ名}、macOS は /Users/{ナヌザヌ名} ↩

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
796