「Puppeteer入門ースクレイピング＋Web操作自動処理プログラミング」の動かないサンプルコード③

#「Puppeteer入門ースクレイピング＋Web操作自動処理プログラミング」の動かないサンプルコード③

「Puppeteer入門ースクレイピング＋Web操作自動処理プログラミング」を購入し、ただいま勉強中です。
これね↓
<a target="_blank" href="https://www.amazon.co.jp/gp/product/4798055204/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4798055204&linkCode=as2&tag=kokkahasan-22&linkId=0774e78e10539fa13675b503875cc1ea">Puppeteer入門 スクレイピング+Web操作自動処理プログラミング</a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=4798055204" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4798055204/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4798055204&linkCode=as2&tag=kokkahasan-22&linkId=87381345b4c9d33a512b6582704198bd"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4798055204&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL160_&tag=kokkahasan-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=kokkahasan-22&l=am2&o=9&a=4798055204" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />


動かないサンプルコードがいくつかありますね。
のちのち使えそうなコードはせっかくなので修正して残しておこうと思いました。

####まずpuppeteerについて

[「Puppeteer入門ースクレイピング＋Web操作自動処理プログラミング」の動かないサンプルコード① ](https://qiita.com/atomyah/items/2b30381dc638afa114d7)の「まずpuppeteerについて」の項目をご覧ください。


#####7章の6，「ブログの画像を保存する」
これも[「Puppeteer入門ースクレイピング＋Web操作自動処理プログラミング」の動かないサンプルコード②](https://qiita.com/atomyah/items/51b157f493142a7d1f09)と同じです。do { 処理 } while(true)の中にawait Promise.all([ 処理 ]);があって、その中にpage.clickがある。そのせいか？ループ途中でハングアップします。

解決方法も同じ。

const nextに、セレクタオブジェクト'(a[rel="next"])'を代入するのではなく、そのhref属性(リンク先URL)を代入。

const next = await page.evaluate(() => document.querySelector(~~'a[rel="next"]')~~);
const next = await page.evaluate(() => document.querySelector(**'a[rel="next"]').href**);




そしてPromise.allの中で、**page.click()**ではなく**page.goto()**を使う。
です。
したがって修正箇所はほんの2箇所です。


```javascript
/// 修正日（2019年2月11日）修正箇所は'///--修正--///'の行です

const puppeteer = require('puppeteer');
const path = require('path');
const request = require('request');
const { promisify } = require('util');
const fs = require('fs');
const delay = require('delay');

/**
 * ファイルのダウンロードを行う.
 * @param {string} url - ダウンロードするファイルのURL
 */
const downloadFile = async (url) => {
  // ダウンロードファイル名の確定.
  const filename = url.split('/').pop();
  // ファイルの取得.
  const res = await promisify(request)({ method: 'GET', uri: url, encoding: null });
  // 成功(200)したかどうか？
  if (res.statusCode === 200) {
    // 成功していればjsと同じフォルダーにファイル出力
    await promisify(fs.writeFile)(path.join(__dirname, filename), res.body, 'binary');
  } else {
    // 失敗した場合はエラー処理.
    throw new Error(`${res.statusCode} ダウンロードエラー`);
  }
};

/**
 * メインロジック.
 */
(async () => {
  // Puppeteerの起動.
  const browser = await puppeteer.launch({
    headless: false, // Headlessモードで起動するかどうか.
    slowMo: 50, // 指定のミリ秒スローモーションで実行する.
  });

  // 新しい空のページを開く.
  const page = await browser.newPage();

  // view portの設定.
  await page.setViewport({
    width: 1200,
    height: 800,
  });

  // ページの遷移.
  console.log('----------------------------------------goto');
  await page.goto('http://ryoichi0102.hatenablog.com/');

await delay(1000); // スクレイピングする際にはアクセス間隔を1秒あける.

  // 先頭の記事のurlを取得し、そのurlへ遷移.
  console.log('----------------------------------------goto');
  const firstPage = await page.evaluate(() => document.querySelector('#main article:nth-child(1) h1.entry-title a').href);
  // const firstPage = 'http://ryoichi0102.hatenablog.com/entry/2018/12/28/101519';
  await page.goto(firstPage);

await delay(1000); // スクレイピングする際にはアクセス間隔を1秒あける.

  // 各記事に対してのそれぞれの処理.
  do {
    console.log('----------------------------------------do');

    const imageUrls = await page.evaluate(() => Array.from(document.querySelectorAll('img.hatena-fotolife')).map(img => img.src));
    for (url of imageUrls) {
      console.log(`Downloading... ${url}`);
      await downloadFile(url);
    }

    console.log('----------------------------------------eval next');
    // 最後の記事までたどると次へボタンは表示されないので、その場合はループを抜ける.
    ///---修正---/// const next = await page.evaluate(() => document.querySelector('a[rel="next"]'));
    const next = await page.evaluate(() => document.querySelector('a[rel="next"]').href);
    console.log('--------------------------------------nextのhrefは、' + next);  

    if (next === null) {
      break;
    }
    
    // process.on('unhandledRejection', console.dir); // Promise内の捕捉されなかった例外について表示する

    // 次のページを読み込む.
    console.log('----------------------------------------next');

    await Promise.all([
        console.log('----------------------------------------inside Promise.all'),  
        page.waitForNavigation({ waitUntil: 'load' }),
        ///---修正---/// page.goto('a[rel="next"]'),
        page.goto(next),
    ]);


    await delay(1000); // スクレイピングする際にはアクセス間隔を1秒あける.
  } while (true);

  // ブラウザの終了.
  console.log('----------------------------------------close');
  await browser.close();
})();
```