雑にpuppeteerでページをクローリングして画像を保存するやつ


雑にpuppeteerでページをクローリングして画像を保存するやつ

最近クローラを書いていたのでメモ
https://adventar.org/calendars/4021

puppeteerでクローリングする際はimgタグのsrcをダウンロードしなくても、 response.buffer() の画像を保存するだけで良い。
SPAのサイトとかも読み込むだけで良いので楽にダウンロード出来る。

とりあえずwikipediaのみかんの画像を集める。

const fs = require("fs");
const path = require('path');
const puppeteer = require('puppeteer');

// 画像を保存するPATHの設定
const SAVE_DIR = path.resolve(__dirname,"images" );

const USER_AGENT = "user agent"
const sleep_time = 1000;
const time_out = 10000;

const headless = true;

// このregexにmatchするものだけ保存する
const download_image_path = "^https:\/\/.*wikimedia.org\/wikipedia/commons.*\.jpg";

// クローリングするページ
const urls = [
    "https://ja.wikipedia.org/wiki/%E3%82%A6%E3%83%B3%E3%82%B7%E3%83%A5%E3%82%A6%E3%83%9F%E3%82%AB%E3%83%B3",
    "https://ja.wikipedia.org/wiki/%E5%86%B7%E5%87%8D%E3%81%BF%E3%81%8B%E3%82%93",
    "https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%97%E3%83%95%E3%83%AB%E3%83%BC%E3%83%84"
];

(async () => {
    // 起動処理
    let browser = await puppeteer.launch({ headless: headless });
    const page = await browser.newPage();

     // UAを設定する
     await page.setUserAgent(USER_AGENT);

     // pageのレスポンス時のListenerを設定する
     const saveFile = async response =>{
         const url = response.url();
         if (response.request().resourceType() === 'image') {
             response.buffer().then(async file => {
                 const fileName = url.split('/').pop();
                 if(  url.search(download_image_path) != -1){
                     const files = fs.readdirSync(SAVE_DIR);
                     const filePath = path.resolve(SAVE_DIR, fileName);
                     const writeStream = fs.createWriteStream(filePath);
                     writeStream.write(file);
                 }
             },error => {
                 console.error(error)
             })
         }
     }
     // Listenerを設定
    await page.on('response', saveFile);

    // クローリングを行う
    for (const url of urls) {
        console.log(`get page :${decodeURI(url)}`)
        try {
            // ページに遷移する
            await page.goto(url, {waitUntil: 'networkidle0', timeout: time_out});
            await page.waitFor(sleep_time);
        } catch (error) {
            // ページが取得できなかった際はページをファイルに書き出す
            console.error(e);
            fs.appendFile("missing_pages.txt",`${url}\n`);
        }
    }
    await browser.close();
})();
$ node index.js

get page :https://ja.wikipedia.org/wiki/ウンシュウミカン
get page :https://ja.wikipedia.org/wiki/冷凍みかん
get page :https://ja.wikipedia.org/wiki/グレープフルーツ

こんな感じで集まる