HyeGyeong
HyeGyeong 프로그래머를 꿈꾸며 JavaScript 공부 중

4주 프로젝트 시작

4주 프로젝트 시작

4주 프로젝트 시작

  • 기업협업 프로젝트에 참여하게 됐다.
  • 자세한 사항은 얘기할 수 없으나 주력 상품에 대한 데이터를 많이 모으고 그 데이터를 시각화해서 보여줘야 하는 프로젝트.

Crawling

  • 많은 데이터를 모으기 위한 방법.
  • 사람이 데이터를 모으는 과정을 자동화 함.
  • JavaScript를 이용하길 원했기 때문에 Node.js의 모듈인 Puppeteer를 사용할 예정.

Crawling을 하면서 생긴 문제

  • 데이터를 가져오는 것은 됐으나 스크롤을 하면서 앞의 내용이 없어지는 현상이 있음. 많은 데이터가 로딩됐을 때 느려지는 현상을 막기 위한 기능인 듯. 그 사이트를 사용할 때는 편했지만 지금은 불편함ㅜㅜ.
  • 앞부분에 나온 데이터 + 마지막 부분에 있는 데이터 일부만 가져오고 있음.
  • 내용을 수집하기 전에 스크롤이 되서 생기는 문제일 거라고 추측됌.
  • 아직 수정 전이지만 요소가 사라지지 않는 사이트에서는 사용 가능하니까 코드 남김.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const fs = require('fs');
const puppeteer = require('puppeteer');

function extractItems() {
  const extractedElements = document.querySelectorAll('img'); // img tag selector
  const items = [];
  for (let element of extractedElements) {
    items.push(element.getAttribute('src')); // items array에 src 주소 push
  }
  return items;
}

async function scrapeInfiniteScrollItems( // 스크롤하면서 data 수집
  page, // crawling할 site url
  extractItems, // 수집된 data
  itemTargetCount, // data count limit
  scrollDelay = 1000 // scroll term
) {
  let items = [];
  try {
    let previousHeight;
    while (items.length < itemTargetCount) {
      // items의 길이가 itemTargetCount보다 작으면 반복
      items = await page.evaluate(extractItems); // eval과 같음. function을 invoke
      previousHeight = await page.evaluate('document.body.scrollHeight'); // body의 scrollHeight 계산
      await page.evaluate('window.scrollTo(0, document.body.scrollHeight)'); // scrollHeight로 스크롤 이동
      await page.waitForFunction(
        // Function to be evaluated in browser context.
        `document.body.scrollHeight > ${previousHeight}`
      );
      await page.waitFor(scrollDelay); // scrollDelay만큼 wait
    }
  } catch (e) {}
  return items;
}

(async () => {
  const browser = await puppeteer.launch({
    headless: false, // 실행되는 화면을 눈으로 확인할 수 있음.
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  });
  const page = await browser.newPage();
  page.setViewport({ width: 1280, height: 926 });

  // 원하는 사이트로 이동
  await page.goto('https://www.example.com');

  // Scroll and extract items from the page.
  const items = await scrapeInfiniteScrollItems(page, extractItems, 732);

  // Save extracted items to a file.
  fs.writeFileSync('./items.txt', items.join('\n') + '\n'); // items.txt에 items data를 삽입

  // Close the browser.
  await browser.close(); // 작업이 끝나면 브라우저 창을 닫음.
})();