웹 스크래핑을 할 때 일반적으로 많이 사용하는 언어는 아마 파이썬일 것이다.
다른 언어에 비해 배우고 쉽고, 웹 스크래핑에 특화된 라이브러리들이 많기 때문일 것이다.
그러나 JavaScript에 익숙한 사람이라면 새로운 언어를 배우지 않고 node 환경에서 웹 스크래핑을 하는 것도 좋은 선택지라고 생각한다.
https://blog.apify.com/web-scraping-javascript-vs-python/
Web scraping in JavaScript vs. Python
Learn how to choose the right tools for web scraping in 2024.
blog.apify.com
JavaScript is rightfully referred to as the language of the web. Close to 97.8% of all websites use it as a client-side programming language. Not surprisingly, some of the most advanced web scraping and browser automation libraries are also written in JavaScript, making it even more attractive for those who want to extract data from the web. Additionally, JavaScript boasts a large and vibrant community. There's plenty of information available online, so you can easily find help whenever you feel stuck on a project.
JavaScript는 당연히 웹의 언어라고 불립니다. 모든 웹사이트의 약 97.8%가 이를 클라이언트 측 프로그래밍 언어로 사용합니다. 놀랍지 않게 도 가장 진보된 웹 스크래핑 및 브라우저 자동화 라이브러리 중 일부 도 JavaScript로 작성되어 웹에서 데이터를 추출하려는 사람들에게 더욱 매력적입니다. 또한 JavaScript는 크고 활기찬 커뮤니티를 자랑합니다. 온라인에서 많은 정보를 얻을 수 있으므로 프로젝트에서 막혔을 때 쉽게 도움을 찾을 수 있습니다.
https://blog.apify.com/web-scraping-javascript-vs-python/
1. 학습 곡선
아마 웹 개발자라면 대부분 할 줄 아는 JavaScript로 코드 구현이 가능하다. 하지만 한가지 유의할 점이 있다면 점점 ES 모듈 지원이 확대되고 있지만 node는 대부분 CommonJS 모듈을 사용한다는 점이다.
// math.js (CommonJS 모듈)
exports.add = function(a, b) {
return a + b;
};
exports.multiply = function(a, b) {
return a * b;
};
// app.js (CommonJS 모듈 사용)
const math = require('./math');
console.log(math.add(2, 3)); // 5
console.log(math.multiply(4, 5)); // 20
// math.js (ES 모듈)
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
// app.js (ES 모듈 사용)
import { add, multiply } from './math';
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
frontend에서 사용하던 라이브러리와 기능을 친숙하게 사용할 수도 있다. Axios를 활용한 HTTP 요청, Async/Await 비동기 처리 등
const axios = require('axios');
async function scrapeWebpage(url) {
try {
const { data } = await axios.get(url);
const title = data.match(/<title>(.*?)<\/title>/)[1];
const content = data.match(/<body>(.*?)<\/body>/s)[1].trim();
console.log('Title:', title);
console.log('Content:', content);
} catch (error) {
console.error('Error scraping webpage:', error);
} finally {
console.log('Scraping process completed.');
}
}
2. 정적 웹 스크래핑 성능
다른 웹 스크래핑 언어나 프레임워크에 비해 뒤쳐지지 않을 만큼 빠른 속도의 성능을 발휘한다. 그 이유 중 한 가지만 뽑자면 비동기와 동기 처리가 자유롭게 사용 가능하다는 것이다.
예를 들어 A 사이트를 스크래핑 후 데이터를 가공해 저장하거나, B 사이트의 데이터와 비교할 땐 비동기 처리가 필요하다. 아래는 후자의 예시 코드
try {
// a 사이트 데이터 스크래핑
const aResponse = await axios.get('https://www.example.com/a');
const aData = aResponse.data;
console.log('A site data:', aData);
// b 사이트 데이터 스크래핑
const bResponse = await axios.get('https://www.example.com/b');
const bData = bResponse.data;
console.log('B site data:', bData);
// 데이터 비교
console.log('Comparing data...');
if (aData.price === bData.price) {
console.log('Prices are the same!');
} else {
console.log('Prices are different!');
}
}
반면에 A 사이트와 B 사이트의 데이터 스크래핑이 동기 방식으로 동시에 병렬 작업이 가능하다면 아래와 같이 수정이 가능하다.
try {
// a 사이트와 b 사이트 데이터 동시에 스크래핑
const [aResponse, bResponse] = await Promise.all([
axios.get('https://www.example.com/a'),
axios.get('https://www.example.com/b'),
]);
const aData = aResponse.data;
const bData = bResponse.data;
console.log('A site data:', aData);
console.log('B site data:', bData);
// 데이터 비교
console.log('Comparing data...');
if (aData.price === bData.price) {
console.log('Prices are the same!');
} else {
console.log('Prices are different!');
}
}
이런 식으로 상황에 따라 동기/비동기 처리 적용이 가능하다는 것이 큰 장점이다.
3. 동일한 DB connection pool 사용 가능
만약 서버내의 다른 파일에서 MYSql2를 이용해 같은 DB를 사용한다면 같은 pool 활용이 가능하다.
새로운 연결을 생성하지 않고 기존 pool을 사용할 수 있고, pool을 닫는 시점도 원하는 순간에 제어 가능하기 때문에 리소스 사용량을 줄일 수 있다.
https://sidorares.github.io/node-mysql2/docs#using-connection-pools
Quickstart | Quickstart
MySQL client for Node.js with focus on performance
sidorares.github.io
4. cheerio
https://proxyway.com/guides/the-best-node-js-libraries-for-web-scraping
6 Best Node.js Libraries for Web Scraping in 2024 - Proxyway
Web scraping with Node.js isn’t difficult with the right set of tools. Check out 6 Node.js libraries and find the perfect match for you.
proxyway.com
지난번 PHP 컨버팅 때도 그렇고 이번 Python 컨버팅에도 cheerio 라이브러리를 사용하였다.
google에서 만든 puppeteer도 있었지만 몇 가지 이유로 cheerio 라이브러리르 선택했다.
1. 정적 페이지
2. javascript 랜더링 필요 없음
3. 요소의 value만 필요
4. 전체 HTML DOM 트리를 다룰 필요 없음
만약 이미지, 파일 등 HTML 요소 외의 것이 필요해 스크래핑 범위를 넓혀야 했다면 puppeteer를 사용했을 텐데, 여러 상황을 따져봤을 때 성능, 속도면에서 cheerio가 더 적합했다.
jQuery를 사용해 봤다면 cheerio를 더 쉽게 사용할 수 있고, VanillaJS를 할 줄 안다면 이해하기 수월할 수 있을 것이다.
// 선택자 사용
jQuery: $('h1')
Cheerio: $('h1')
VanillaJS: document.querySelector('h1')
// 속성 선택
jQuery: $('a[href="https://www.example.com"]')
Cheerio: $('a[href="https://www.example.com"]')
VanillaJS: document.querySelector('a[href="https://www.example.com"]')
// DOM 탐색
jQuery: $('ul li').first()
Cheerio: $('ul li').first()
VanillaJS: document.querySelectorAll('ul li')[0]
// DOM 조작
jQuery: $('p').text('New text')
Cheerio: $('p').text('New text')
VanillaJS: document.querySelector('p').textContent = 'New text'
이것 외에도 forEach와 유사한 each, find, text, attr 등을 사용할 수 있다.