Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9173

Puppeteerでスクレイピング

$
0
0

今更感はあるのですが、Puppeteerでスクレイピングしてみました。

環境

Node.js 12.18.3
Puppeteer 5.5.0
TypeScript 4.1.3

やったこと

環境の準備

まず、適当なディレクトリを初期化して、必要なモジュールをインストールしていきます。

$ npm init -y
$ npm i puppeteer
$ npm i -D typescript ts-node @types/node @types/puppeteer
$ npx tsc --init

今回、TypeScriptはts-nodeを使って実行します。
そのため、package.jsonに下記のスクリプトを追記します。

package.json
〜略〜"scripts":{"start":"ts-node src/index.ts"},〜略〜

実際のコード

配列で用意しておいたURLを直列で順番にスクレイピングしていく、というサンプルを作っていきます。
先に全体のコードを置いておきます。

src/index.ts
constpuppeteer=require('puppeteer');constpath=require('path');constfs=require('fs');// スクレイピング対象のURLconsturls=['https://qiita.com/','https://developer.mozilla.org/en-US/'];// スクレイピングconstcrawl=async(url:string)=>{// ファイル名用の現在日付作成constnow=(()=>{constd=newDate();return`${d.getFullYear()}_${(d.getMonth()+1)}_${d.getDate()}_${d.getHours()}-${d.getMinutes()}-${d.getSeconds()}`;})();// ブラウザー開くconstbrowser=awaitpuppeteer.launch({headless:false,slowMo:50,defaultViewport:{width:1280,height:800}});// 新規タブconstpage=awaitbrowser.newPage();//  URLへアクセスawaitpage.goto(url);// ScreenShot保存constimgPath=path.join('./ss',`${now}.png`);awaitpage.screenshot({path:imgPath,fullPage:true,});// ドキュメントの情報を取得constmetaData=awaitpage.evaluate(()=>{return{'title':document.querySelector('title')?.textContent,'description':(<HTMLMetaElement>document.querySelector('meta[name="description"]'))?.content,'h1':document.querySelector('h1')?.textContent,};});// セッション終了awaitbrowser.close();return{img:imgPath,...metaData}};// 対象URL分スクレイピング処理を実行するconsthandleCrawler=async()=>{constr=[];for(letvofurls){r.push(awaitcrawl(v));}console.log(r);};(async()=>{// スクリーンショット保存用のディレクトリがない場合if(!fs.existsSync('ss')){// ScreenShot保存ディレクトリ作成後、実行fs.mkdir('ss',()=>{handleCrawler();});}// 保存用ディレクトリが既存の場合、そのまま実行else{handleCrawler();}})();

何をやっているか

まずは、Puppeteerを使って、Chromeを起動します。

src/index.ts
// 〜略〜// ブラウザー開くconstbrowser=awaitpuppeteer.launch({headless:false,slowMo:50,defaultViewport:{width:1280,height:800}});

今回、実際にChromeが起動しているところを確認したいので、headlessにfalseを指定して、Chromeがnon-headlessで起動するように指定しています。また、slowMoを指定することで、指定されたミリ秒数分、操作を遅延させています。

その後、タブを開いて対象URLに遷移し、スクリーンショットを保存します。

src/index.ts
// 〜略〜// ScreenShot保存constimgPath=path.join('./ss',`${now}.png`);awaitpage.screenshot({path:imgPath,// ここでスクリーンショットを保存するローカルのパスを指定fullPage:true,// type: 'jpeg',// quality: 0});

オプションにローカルのパスを指定すると、そこにスクリーンショットが保存されます。
qualityオプションを渡すことで画像の解像度を指定することができます。
試しに使ってみたところ、ページ全体のスクリーンショットが1.3MBほどあったページも、quality: 0を指定すると88KBほどになりました。サーバーの容量に制限があるときなどには使えるかも知れません。

続いて、ドキュメントの情報を取得しています。

src/index.ts
// ドキュメントの情報を取得constmetaData=awaitpage.evaluate(()=>{return{'title':document.querySelector('title')?.textContent,'description':(<HTMLMetaElement>document.querySelector('meta[name="description"]'))?.content,'h1':document.querySelector('h1')?.textContent,};});

今回ここで少しハマったのですが、素直に

'description':document.querySelector('meta[name="description"]')?.content,

としてしまうと

Property 'content' does not exist on type 'Element'.

と怒られてしまいました。  

HTMLElementのインターフェースにはcontentというプロパティが無いことが原因なようで、HTMLMetaElementにキャストしてあげる必要があったようです。
大変助かりました。>https://qiita.com/vsanna/items/201d4af29086a01b6b12

実行

実際に上記のソースコードを実行してみます。
npm startで実行されます。

$ npm start

実行したターミナルの標準出力に、スクレイピングの結果が出力されました。

出力結果
[
  {
    img: 'ss/2020_12_16_16-56-39.png',
    title: 'Qiita',
    description: 'Qiitaは、プログラマのための技術情報共有サービスです。 プログラミングに関するTips、ノウハウ、メモを簡単に記録 &amp; 公開することができます。',
    h1: 'How developers code is here.'
  },
  {
    img: 'ss/2020_12_16_16-56-44.png',
    title: 'MDN Web Docs',
    description: 'The MDN Web Docs site provides information about Open Web technologies including HTML, CSS, and APIs for both Web sites and progressive web apps. It also has some developer-oriented documentation for Mozilla products, such as Firefox Developer Tools.',
    h1: 'Resources for developers, by developers.'
  }
]

/ss配下にはスクリーンショットが保存されているのが確認できました。

$ ls -la ss
出力結果
total 3512
drwxr-xr-x  4 xxxx  staff      128 Dec 16 16:56 .
drwxr-xr-x  9 xxxx  staff      288 Dec 16 16:56 ..
-rw-r--r--  1 xxxx  staff  1340232 Dec 16 16:56 2020_12_16_16-56-39.png
-rw-r--r--  1 xxxx  staff   453752 Dec 16 16:56 2020_12_16_16-56-44.png

最後に

Puppeteer自体の使い方もとてもシンプルで、思っていたよりも簡単にWebスクレイピングを実装できました。
扱いやすいライブラリにめちゃくちゃ感謝です。(つづりが難しい...


Viewing all articles
Browse latest Browse all 9173

Trending Articles