Node JS/puppeteer

[PUPPETEER] 병렬로 처리하기

seongjin08 2022. 7. 30. 14:18

크롤링을 하기위해서 작업하던 도중

수백 수천개의 정보를 크롤링 해야하는 데 하나씩 처리기 하기에는 시간이 너무 오래걸린다.

병렬로 처리하여 여러개를 동시에 작업 해야한다.

 

기존 하나씩 하는 코드

app.js

const { browser, newPage } = require('./puppeteer')
const { urls } = require("./urls");


(async () => {

    const Browser = await browser();
    // url 배열 만큼 반복문 돌리기 
    for (link of urls) {
        try {
            // 한 브라우져에서 작업하기 위해 인자값으로 브라우져와 urlf를 인자로 준다.
            await newPage(Browser, link)
        } catch (e) {
            // 에러가 나도 계속 진행하기 위해 try 문 사용
            console.log(e);
            continue
        }
    }
})()

puppeteer.js

const puppeteer = require("puppeteer");

// 브라우져 생성하는 함수
const browser = async () => {
    return await puppeteer.launch({
        headless: false,
        args: ["--window-size-1500,1000"],
        slowMo: 40
    })
}

// 페이지 생성하는 함수 
const newPage = async (Browser, url) => {

    const page = await Browser.newPage();
    // 페이지 사이즈 
    await page.setViewport({
        width: 1500,
        height: 1000
    })

    await Promise.all([
        page.goto(url),
        page.waitForNavigation()
    ])
}

module.exports = {
    browser,
    newPage
}

urls.json

module.exports={
    urls:["http://www.naver.com","http://www.google.com","http://www.kakao.com","http://www.daum.net"]
}

 

 

이렇게 작동 할 경우 한 브라우져에 페이지 하나가 로드 완료되고 다음 페이지가 로드되면서 

4개의 페이지가 로드가 완료되는 데 까지 4초 이상의 시간과  이후 크롤링 작업 또한

비효율 적으로 한개씩 작동하게 된다.

 

app.js

const { browser, newPage } = require('./puppeteer')
const { urls } = require("./urls");

const sliceArray = (arr, size) => {
    //원하는 사이즈로 자르고 담을 배열
    const result = [];
    // 자를 시점을 체크하기 위한 변수
    let start = 0;

    // 배열의 사이즈 보다 작을 때만 작동
    while (start < arr.length) {
        // 사이즈 만큼 자르기 
        const cut = arr.slice(start, start + size)
        result.push(cut)
        // 자른 사이즈 만큼 start 숫자 더해주기
        start += size;
    }
    return result;
}

(async () => {
    const Browser = await browser();
    const size = 4;

    const cutting = sliceArray(urls, size);

    // cutting 배열 만큼 반복문 돌리기 
    for (link of cutting) {
        try {
// 사이즈 만큼 나눠진 url 페이지 열어서 작동 
            const test = link.map(async (link) => {
                return await newPage(Browser, link)
            })

            await Promise.all(test)

        } catch (e) {
            // 에러가 나도 계속 진행하기 위해 try 문 사용
            console.log(e);
            continue
        }
    }
})()

 

이렇게 동시에 로드되어 작동 되는 것을 확인 할 수 있다.

javascript 는 비동기 이기 때문에  장점을 활용 하자.

 

'Node JS > puppeteer' 카테고리의 다른 글

puppeteer (기본기)  (0) 2022.07.04