年末年始暇ですね。
暇つぶしに何か作ろうと思ったんですが、何も思いつかず。。。
普段AngularやNestJSでTypescriptばっかり書いてますが、たまにはJavascriptでも書いてみようと思いました。
とりあえずWebページのスクレイピングってやったことないからJavascriptで書いてみるかーということでしょうもないツールを作ってみました。
作ったもの
WebページのURLを指定すると、そのページ内のimgタグの写真をすべてダウンロードするコマンドラインツールです
img-downloader
使い方
- nodeコマンドで
img-downloader.js
を実行します - 引数に対象のWebページURLを指定します
npm install
node img-downloader.js {web-page-url}
結果
output/{YYYYMMDDhhmmss}
ディレクトリに画像が出力されます
実行例
以下のページから画像を取得してみます
https://www.irasutoya.com/2018/12/blog-post_676.html
node img-downloader https://www.irasutoya.com/2018/12/blog-post_676.html
↓ 実行
↓ 出力
指定したページ内の全画像をとってくるので、ロゴやバナーの画像なんかの意図しない画像も取れてしまうのが難点です。。。
技術的な話
すごいシンプルなJavascriptで書いてます。
ほんとはスクレイピングも自前でやろうかと思ったんですが、めんどくさくなってscraperjs使っちゃいました。。
使ってるパッケージ
スクレイピング
scraperjsを扱うためのUtilクラスを作りました。getTargetImgURl()
で指定URLからimgタグのsrc属性をピックアップします。
classScraperUtil{getTargetImgUrl(pageUrl){returnthis.scrape(pageUrl,($)=>{return$('img').map(function(){return$(this).attr('src');}).get();});}scrape(pageUrl,fnScraping){returnnewPromise((resolve,reject)=>{scraperjs.StaticScraper.create(pageUrl).scrape(($)=>fnScraping($)).then(items=>resolve(items)).catch(err=>reject(err));});}}
簡単にスクレイピングできて良いですね。
画像のダウンロード
src属性に指定された値によってダウンロード方法が変わります
URLの場合
- requestパッケージで画像データをGET
- GETしたデータをfsパッケージのwriteFileSyncでファイル出力
- ファイル名はURLから取得
BASE64データの場合
data:image/xxx~
で始まる文字列の場合、BASE64データが指定されていると判断し、以下のように出力しています。
- str.match()で
data:image/xxxx;base64,
を抽出 - 上記で抽出した文字列を除いた文字列(画像データ)をBASE64デコード
- ブラウザ上でないとwindow.atobは使えないため、Bufferを使ってデコードしています
- fsパッケージのwriteFileSyncでファイル出力
- ファイル名は
raw{cnt}.{type}
で出力 - typeは上記で抽出した文字列の画像タイプ(xxxxの部分)を指定
- ファイル名は
最後に
休みボケの中で適当に書いているため、突っ込みどころ満載なコードになってしまいましたが、良い暇つぶしになりました。
Typescriptだと型とかきっちりしてて書いてる途中でエラーに気付けますが、Javascriptだと実行してようやく気付くことが多いので、久々だと意外と難しいですね(笑)
(追記)
Googleの画像検索の結果一括保存したかったのにできてないので、気が向いたらアップデートしていこうかと思います。