うるるをPuppeteerでスクレイピングしてみた

こんにちは!
新卒2年目のKawamotoです!!

今回は自分が担当しているプロジェクトで愛用している,
`Puppeteer`を使ってスクレイピングします！
自社サービスの宣伝も兼ねて,
スクレイピングの対象は, [うるるのコーポレートサイト](https://www.uluru.biz)にしました！

# はじめに
この記事はうるる [Advent Calendar 2019](https://adventar.org/calendars/4548) 21日目の記事です.

`Puppeteer`を勉強するなら下記の本が結構参考になりますよ!!
https://www.amazon.co.jp/dp/B07MJPM15V/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

# 準備
本orWebを駆使して動くように準備!!

# 初期状態
```js:puppeteer.js:
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz');

  await browser.close();
})();

```
とりあえずTopページにアクセスできるようにした.

# 文字列の取得
自社サービスである[シュフティ](https://www.uluru.biz/service/service_shufti)の説明文を取得する.
<img width="1269" alt="スクリーンショット 2019-12-08 0.20.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180668/4eed8d5b-909a-85be-8539-b39c942847e8.png">

```js:puppeteer.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz/service/service_shufti');

  // セレクタを指定
  let shuftiServiceGuide=".entry-content .container-1140.relative p";

  // 要素を取得
  var data = await page.$eval(shuftiServiceGuide, item => {
      return item.textContent;
  });

  console.log(data);

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

結果 :
とれた :clap: 
<img width="823" alt="スクリーンショット 2019-12-08 0.46.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180668/e03d7628-cc9a-ceea-3b2c-a434ffb58fa8.png">

# 画像のダウンロード
自社サービスである[fondesk](https://www.uluru.biz/service/fondesk)の画像を取得する.

```js:puppeteer.js
const puppeteer = require('puppeteer');

// 画像ダウンロードに必要
const fs = require('fs');
const path = require('path');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz/service/fondesk');

  // imgタグの取得
  const img = await page.$('.slick-slide.slick-current.slick-active img');

  // 取得したタグのsrc属性を取得
  const src = await img.getProperty('src');

  // JSHandleオブジェクトの内容をjsonValueで取り出す
  const targetUrl = await src.jsonValue();

  // URL形式で取得できたパスのファイル名部分を取り出す
  const filename = targetUrl.split('/').pop();

  // 直下に保存
  const localfilefullpath = path.join(__dirname, filename)
  const viewSource = await page.goto(targetUrl);
  fs.writeFile(localfilefullpath, await viewSource.buffer(), (error) => {
    if (error) {
      console.log(`error=${error}`)
      return;
    }
  });
  
  await browser.close();
})();
```

結果 :
とれた :clap: 
<img width="1280" alt="スクリーンショット 2019-12-08 1.14.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180668/145c74bc-9351-86b8-4f09-f06d3e588f03.png">

# 画面のキャプチャ
弊社の[20新卒内定者のエンジニア](https://blog.uluru.biz/entry/2019/11/22/121436)が作成した[21新卒採用サイト](https://www.uluru.biz/recruit_newgrads/)のTop画面を全画面キャプチャしてみる.

```js:puppeteer.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz/recruit_newgrads/');

  // fullPageをtrueにすると全画面キャプチャ
  await page.screenshot({ path: 'fullpage.png', fullPage: true});

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

結果 :
とれた :clap: 
<img width="1279" alt="スクリーンショット 2019-12-08 19.57.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180668/d463a9db-c3ca-9507-a39b-92e082d0df08.png">

弊社は21新卒大募集中です!!
https://blog.uluru.biz/entry/2019/11/05/154011

# PDFを取得
弊社のIR情報を取得する.
別タブで開くPDFなので少々工夫が必要.(ヘッドレスモードにしなければ問題ない!)
https://github.com/puppeteer/puppeteer/issues/830

ここではaxiosを使用して取得する!

```js:puppeteer.js
const puppeteer = require('puppeteer');
const fs = require('fs');
const axios = require('axios')

// PDFをダウンロードする関数
async function fetch(url, cookies = '') {
  const res = await axios.get(url, {
    headers: {
      Cookie: cookies,
      Accept: 'application/pdf'
    },
    responseType: 'arraybuffer'
  })
  return res.data
}

(async () => {
  const browser = await puppeteer.launch({
    // headlessモードにする
    headless: true,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz/ir/');

  // 2019.11.14のIR資料
  const img = await page.$('#dataList .irGroup dl:nth-child(1) dd a');
  const src = await img.getProperty('href');
  const targetUrl = await src.jsonValue();

  // cookieの取得
  const cookies = (await page.cookies())
        .map(c => `${c.name}=${c.value};`)
        .join(' ')

  const data = await fetch(targetUrl, cookies);

  fs.writeFileSync('./IR.pdf', new Buffer.from(data), 'binary');

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

結果 :
とれた :clap: 
<img width="1275" alt="スクリーンショット 2019-12-20 23.31.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180668/d40a8d16-6cd0-b676-05d9-fdd6a2d5e5c6.png">

# 取得したファイルなどをS3に送る

バケットの用意や権限の調整は各自で🙇‍♂️

```js:puppeteer.js

const puppeteer = require('puppeteer');
const axios = require('axios')
const AWS = require('aws-sdk');
const uuidv4 = require('uuid/v4')
const s3 = new AWS.S3();
const bucket = 'Hoge';

// PDFをダウンロードする関数
async function fetch(url, cookies = '') {
  const res = await axios.get(url, {
    headers: {
      Cookie: cookies,
      Accept: 'application/pdf'
    },
    responseType: 'arraybuffer'
  })
  return res.data
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
  });

  const page = await browser.newPage();

  await page.goto('https://www.uluru.biz/ir/');

  // 2019.11.14のIP資料
  const img = await page.$('#dataList .irGroup dl:nth-child(1) dd a');
  const src = await img.getProperty('href');
  const targetUrl = await src.jsonValue();

  // cookieの取得
  const cookies = (await page.cookies())
      .map(c => `${c.name}=${c.value};`)
      .join(' ')

  const data = await fetch(targetUrl, cookies);

  const params = {
    Bucket: bucket,
    Key: uuidv4(),
    Body: data
  };

  await s3.putObject(params).promise();

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

# さいごに
Puppeteerを利用すると簡単にスクレイピングができます！
みなさんもWeb上に転がっている情報をPuppeteerでGETしちゃいましょう👍

明日は、アニさんによる記事です！
ご期待ください！