웹사이트에서 정보를 한번만 긁어 가져오는 것을 스크래핑이라합니다.
정보를 원하는 웹사이트에 접속해서 html파일을 받아오고 원하는 정보만 추려내는 작업을 cheerio를 통해 쉽게 할 수 있습니다.
import axios from 'axios';
import cheerio from 'cheerio';
async function getOpenGraph(mydata) {
const myaddress = mydata.contents.split(' ').filter(el => el.includes('http'));
const html = await axios.get(myaddress[0]);
const $ = cheerio.load(html.data);
$('meta').each((_, el) => {
const key = $(el).attr('property')?.split(':')[1]; // ? 옵셔널 체이닝 앞에가 있으면 실행
if (key) {
const value = $(el).attr('content');
console.log(key, value);
}
});
}
const mydata = {
title: '안녕',
contents: '여기는 https://naver.com 입니다!',
};
getOpenGraph(mydata);
네이버에서 받아온 html파일을 cheerio를 통해 meta태그를 찾고
meta태그에서 속성이 property인 경우에 값을 :기준으로 잘라 og:title이면
title을 가져오고 content 속성의 값도 가져와 정보를 저장할 수 있습니다.
이렇게 저장된 정보는 특히 채팅창등에서 해당 url의 미리보기 데이터로 활용됩니다.
한번이 아닌 지속적으로 정보를 긁어오고싶다면 puppeteer로 크롤링이 가능합니다.
import puppeteer from 'puppeteer';
async function startCrawling() {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
await page.goto('https://www.goodchoice.kr/product/search/2');
await page.waitForTimeout(1000);
const stage = await page.$eval(
'#poduct_list_area > li:nth-child(2) > a > div > div.name > div > span',
el => el.textContent
);
const location = await page.$eval(
'#poduct_list_area > li:nth-child(2) > a > div > div.name > p:nth-child(4)',
el => el.textContent
);
const price = await page.$eval(
'#poduct_list_area > li:nth-child(2) > a > div > div.price > p > b',
el => el.textContent
);
// #poduct_list_area > li:nth-child(3) > a > div > div.price > p > b
console.log(stage);
console.log(location.trim());
console.log(price);
await browser.close();
}
startCrawling();
puppeteer는 사이트자체를 복제하여 브라우저로 띄울수 있으며 내부 로그인등도 가능하게 해줍니다.
import puppeteer from 'puppeteer';
import mongoose from 'mongoose';
import { Stock } from './models/stock.model.js';
mongoose.connect('mongodb://localhost:27017/codecamp');
async function startCrawling() {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720 });
await page.goto('https://finance.naver.com/item/sise.naver?code=005930');
await page.waitForTimeout(1000);
const myIframePage = await page
.frames()
.find(iframe => iframe.url().includes('/item/sise_day.naver?code=005930'));
for (let i = 3; i <= 7; i++) {
await page.waitForTimeout(3000); // 텀을 줘서 차단안당하게. (for문으로 반복하면 너무빠르게 요청되기에 공격차단)
const mydate = await myIframePage.$eval(
`body > table.type2 > tbody > tr:nth-child(${i}) > td:nth-child(1) > span`,
el => el.textContent
);
const myprice = await myIframePage.$eval(
`body > table.type2 > tbody > tr:nth-child(${i}) > td:nth-child(2) > span`,
el => el.textContent
);
const mystock = new Stock({
name: '삼성전자',
date: mydate,
price: Number(myprice.replace(',', '')),
});
await mystock.save();
console.log(`날짜: ${mydate}, 가격: ${myprice}`);
}
await browser.close();
}
startCrawling();
사이트에서 iframe을 사용할경우 iframe의 정보를 불러오기 위해 추가적인 코드가 필요합니다.
원하는 데이터를 원하는 만큼 for문으로 가져와 DB에 저장할 수 있습니다.