본문 바로가기
[IT] Node.JS/[웹크롤링] Puppeteer

[웹 크롤링] Node.js Puppeteer - investing 원자재(금은/천연가스/원유) 가격 가져오기

by 오리엔탈킴 2022. 2. 25.

안녕하세요, Headless Browser를 이용한 웹 크롤링(Crawling) 및 웹 스크래핑(Scraping) 툴 Puppeteer를 이용실시간 원자재(금 은,천연가스,원유) 선물 가격 혹은 지수가격(코스피,나스닥,S&P,러셀,FTSE 등)을 자동으로 가져오는 코드를 구현해보도록 하겠습니다.

실시간 원자재 선물가격 이나 주가 지수 가격은 investing.com이라는 사이트에서 가져오도록 하겠습니다. investing.com에 정말 많은 경제지표들이 있는데, 사실 원자재, 주가 지수 외에 암호화폐(비트코인,이더리움,리플), 환율(달러, 유로, 엔), ETF/펀드 등도 유사하게 구현하여 읽어 올 수 있습니다. 

페이지 분석

먼저 웹 크롤링을 하려면 어떤 값을 가져오면 될지 직접 사이트에 들어가서 분석을 해야 하는데, 해당 페이지에서 내가 가져올 값을 특정할 수 있는 아래의 HTML Element Selector 값 중 적절한 것을 찾으시면 됩니다. 아래 내용은 CSS Selector로 [https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Selectors] 해당 페이지를 참고하시면 됩니다. 페이지 내에서 유일한 값이면 구현이 쉬워지며, 유일 값을 특정할 수 없을 경우 어떤 값을 검색했을 때 고정된 순서가 있다면 구현이 가능 합니다.

  • 태그 값 (<a>, <h1> 등) : a
  • Class (<div class="AA">) : .AA
  • ID (<div id="BB">) : #BB
  • Attribute(<div CC="DD">) : [CC="DD"]

우선 제가 가장 관심이 있는 천연가스 가격을 알 수 있는 페이지를 investing.com (https://kr.investing.com/commodities/natural-gas)에서 들어가면, 중간에 아래와 같은 실시간 가격 세션이 있는 것을 볼 수 있습니다. 여기서 가격 텍스트만 읽어 오도록 하겠습니다.

Price Area
Price Area

 

크롬에서 F12를 눌러서 개발자 도구를 실행 후, Elements탭에서 상단 [select an element] 아이콘을 클릭하고 해당 가격 부분을 클릭하면, 가격 부분의 HTML Tag가 아래와 같이 구성되어 있는 것을 확인할 수 있습니다.

Html Element
Html Element

<div data-test="instrument-header-details">
....생략....
	<span class="text-2xl" data-test="instrument-price-last">가격</span>
....생략....
</div>

 

위와 같은 구조에서, data-test="instrument-price-last"라는 Attribute를 가진 Span태그에 있는 가격 데이터를 가져오려고 합니다. 구조를 보면 data-test="instrument-header-details"라는 Attribute를 가진 DIV 태그 밑에, data-test="instrument-price-last"라는 Attribute를 가진 Span태그로 특정하면 페이지 내에서 유일 값인 걸로 예상이 됩니다. 위의 내용을 Selector로 작성하면 아래와 같습니다.

  • div[data-test="instrument-header-details"] span[data-test="instrument-price-last"]

element 탭에서 [ctrl] + [F] 눌러서 위의 값을 검색했을 때 1개만 검색이 되므로 페이지 내에서 유일 값임을 확인할 수 있습니다.

 

Node.js Puppeteer 크롤링 구현

본격적으로 investing.com에서 원자재 및 지수 가격 크롤링(javascript, node.js)을 하는 것을 구현해보도록 하겠습니다. Node.js Puppeteer 내용은 기존 포스트에서 구현했던 내용을 토대로 구현을 할 예정이라 아래 포스트를 통해 사전 세팅은 진행하시면 됩니다.

[Node.js] Headless 브라우저 웹 크롤링 Puppeteer 소개, 설치 및 샘플 예제

아래와 같이 간략히 구현이 가능한데, 먼저 내가 가져오고 싶은 원자재 혹은 지수의 정보와 URL이 있는 맵을 수동으로 생성합니다. Puppeteer를 런처 후 브라우저를 열어서 생성된 Map의 url를 반복문을 통해 차례로 방문하면서 위에 selector를 이용하여 가격정보를 가져와서 콘솔 창에 출력하는 예제입니다.

가격의 값을 가져오는 부분에서 page.$eval 메서드 부분이 나오는데, 해당 내용은 javascript에서 document.queryselector를 이용하여 대상을 찾고 innerHTML을 이용해서 하위 HTML 값을 가져오는 내용과 동일한 코드입니다.

 

const puppeteer = require('puppeteer-core');

// 각 원자재 이름과 URL 정보가 있는 MAP을 생성
const urlMap = new Map([
  ['silver','https://kr.investing.com/commodities/silver'],
  ['wti','https://kr.investing.com/commodities/crude-oil'],
  ['gas','https://kr.investing.com/commodities/natural-gas']
]);

(async () => { 
  // puppeteer 실행 (puppeteer-core가 아닌 puppeteer를 설치하면 내장 크로미움으로 실행되므로 executablePath 설정 불필요)
  const browser = await puppeteer.launch({ 
    executablePath: 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe' 
    //,headless : false
    });
  const page = await browser.newPage(); 

  // url map에서 Key 값을 가져와서 반복문 실행
  let urlKeys = urlMap.keys();
  for(var v of urlKeys){

    // map에 저장된 url 가져와서 순차적으로 방문
    var url = urlMap.get(v);
    await page.goto(url);

    // 가격 보여지는 DIV가 페이지 나타나면, 가격 값을 가져 옴
    await page.waitForSelector('div[data-test="instrument-header-details"]'); 
    let price = await page.$eval('div[data-test="instrument-header-details"] span[data-test="instrument-price-last"]', x=> x.innerHTML);
  
    console.log(v,":",price,"$");
  }

  await browser.close();

})();

Console 결과
Console 결과

 

위의 코드를 런하면 위와 같이 콘솔 창에 investing.com에서 실시간으로 크롤링해온 원자재 가격 정보가 출력되는 것을 확인할 수 있습니다. 이렇게 가져온 데이터를 DB에 저장하거나 API 서버를 만들어서 다른 시스템에 전달하는 등으로 활용이 가능한데 해당 내용은 추후 작성할 예정입니다.

 

반응형

댓글