puppeteerでスクショを撮る時に調べた4つのこと

# 背景
**<font color="red">※ここは読み飛ばしていただいて大丈夫です。</font>**


WinActorというツールをご存知でしょうか。
RPA（ロボティック・プロセス・オートメーション）ツールとして、とても便利な良いツール（らしい）です。

ただ、買うと高いです。
年間で諭吉が100人とか飛んでいくレベルです。

さてさて、このツールですが、たまたま私が属している会社は購入していました。
そこで、とあるウェブサイトのスクショを撮りたいという要望があり、WinActorが使えないかという話が出ていたので試したわけです。

なるほど、ふむふむと説明資料を読み込みながら思いました。

「puppeteerで良いのでは？」

もちろん、**今回の件に関しては**puppetterで出来そうだったというだけで、
**puppetterの方が優れているとかいうつもりはありません**。

WinActorの方が色々とできる幅も広そうだし、便利そうなツールだなーと思いました。
社内で使うなら、使い倒せばいいと思います。（購入しているわけですし）

ただ、調査はするものの、実際に使うのは当社じゃなかったので、
**「WinActorというツールを購入していただければ、希望通りスクショを撮れそうです！諭吉100人分の予算とってください！あ、毎年かかります！」**
とは言いにくいです。

いえね、費用対効果的に元が取れるなら良いと思いますし、他の業務でWinActorを使い倒せるような余地があるなら購入した方が色々幸せになるのではと思いますよ？
今回の用途だけなら厳しいのではないかなーと思ったというだけです。

ともあれ、そういうわけで、「試しにpuppeteerだとどうなるかなー」と試した備忘録です。
スクショを撮る際に、調べてもパッと見つからなかった「個人的に知りたかったこと」を載せています。

あ、ちなみに結論から言えば、puppetterでできそうでした。

# スクリーンショット

まずは普通に撮ってみます。
保存先のpathに関してはローカル環境に合わせて書き換えてください。

```typescript

export class UsePuppeteer {
	private browser: Browser;

	constructor() {

		// テスト用にheadlessにせず、動作にも遅延をかける
		puppeteer.launch( {
			headless: false,
			slowMo: 10,
			args: [ "--no-sandbox", "--disable-setuid-sandbox" ]
		} )
			.then( ( browserObj ) => {
				this.browser = browserObj;
				return this.test();
			} )
			.catch( ( err ) => {
				throw err;

	}
	async test(): Promise<any> {
		const page = await this.browser.newPage();
		await page.setViewport( {
			width: 1200,
			height: 800
		} );

		await page.goto( "https://blog.qiita.com/", { waitUntil: "domcontentloaded" } );

		await page.screenshot( {
			path: "/Users/hoge/Desktop/test.png"
		} );

		await page.close();
	}
}
```

撮った画像は以下の通り。

<img src="https://camo.qiitausercontent.com/e5ef4b53a2ae814d722b69ef8896e3fe0947d916/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33333334372f38656530363433622d343333622d633731662d626465332d6432393232373736393637392e706e67" alt="test0.png" data-canonical-src="https://qiita-image-store.s3.amazonaws.com/0/33347/8ee0643b-433b-c71f-bde3-d29227769679.png" width="500">

## 注意

**<font color=red>以降のコードは、普通に撮った場合のコードから変更があった部分のみ載せます。</font>**

## jpegで保存するようにしてスクショ

```ts

		await page.screenshot( {
			path: "/Users/hoge/Desktop/test.jpg",
			type: "jpeg",
			quality: 100
		} );
```

**メモ**

* typeでjpegを指定しなくても、pathで指定している保存ファイル名がjpgならjpgで保存される。
* qualityを指定しないと、たぶん80が適用される。（出力されるファイルサイズで見ただけ）
* qualityはpngで保存しようとした時に指定していると、エラー。
    * `UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: options.quality is unsupported for the png screenshots`

## fullPageをtrueでスクショ

```ts
		await page.screenshot( {
			path: "/Users/hoge/Desktop/test.png",
			fullPage: true
		} );
```

撮った画像は以下の通り。

<img src="https://camo.qiitausercontent.com/5ca6d01f33b2341840527ba9120a77946fafc2d4/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33333334372f39653637366532372d323763352d386135322d663337362d3665656565386662336631612e706e67" alt="test.png" data-canonical-src="https://qiita-image-store.s3.amazonaws.com/0/33347/9e676e27-27c5-8a52-f376-6eeee8fb3f1a.png" height="600">


プレビューのインスペクタは以下の通り。

<img width="366" alt="スクリーンショット.png" src="https://qiita-image-store.s3.amazonaws.com/0/33347/e93ea8eb-7368-4f1a-861a-ad437a645f61.png">

**メモ**

* fullPageをtrueにした場合、幅はそのままで、高さが可変になる。

## PCの画面サイズを超えるサイズでスクショ
「上述のfullPageでできたのだから、もしや最初のwidthとheightの指定を変えれば、すごい大きいスクショが撮れるのでは？」
というところからスタート。
さて結果はいかに。

```ts
		await page.setViewport( {
			width: 7680,
			height: 4320
		} );
```

撮った画像は以下の通り。

<img src="https://camo.qiitausercontent.com/26be02af5b1f090c1dd195949aff27f29c036282/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33333334372f61386430613766362d643136332d663035382d346265342d6137313735393565656339342e706e67" alt="test.png" data-canonical-src="https://qiita-image-store.s3.amazonaws.com/0/33347/a8d0a7f6-d163-f058-4be4-a717595eec94.png" width="500">


プレビューのインスペクタは以下の通り。

<img width="366" alt="スクリーンショット.png" src="https://qiita-image-store.s3.amazonaws.com/0/33347/5a991272-4c16-b828-493e-f87e22934d18.png">


**メモ**

* PCの画面に表示しきれないサイズでもスクショできる。


## 特定の要素（領域）だけスクショ

```ts

		// 描画領域を取得
		const rect = await page.evaluate( () => {
			const rect = document.getElementById( "masthead" ).getBoundingClientRect();
			return {
				x: rect.left,
				y: rect.top,
				width: rect.width,
				height: rect.height
			};
		} );

		await page.screenshot( {
			path: "/Users/hoge/Desktop/test.png",
			clip: rect
		} );
```

撮った画像は以下の通り。

<img src="https://camo.qiitausercontent.com/fe60ace579a3984b33c2426f2fda51a1701f527e/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33333334372f37666666613838352d653337302d373337312d616361332d3131623132633462666231642e706e67" alt="test.png" data-canonical-src="https://qiita-image-store.s3.amazonaws.com/0/33347/7fffa885-e370-7371-aca3-11b12c4bfb1d.png" width="500">

試しに、imgタグを指定するのではななく、その親のheader部分の要素のサイズに従って保存しました。

**メモ**

* 特定の領域のみスクショで保存したい場合はclipを使う。
* 特定の要素の領域をスクショで保存したい場合は、`getBoundingClientRect()`で取得した値を利用してどうにかすると楽。