웹 스크래핑 프로세스를 통해 특정 웹 사이트에서 정보를 추출할 수 있습니다. 사이트는 HTML을 사용하여 페이지의 구조와 콘텐츠를 정의합니다. HTML 코드가 잘 정리되고 의미 있는 경우, 가치 있는 데이터를 식별하고 검색하는 것이 용이합니다.
일반적으로 웹 스크래핑 도구를 사용하여 데이터를 추출하고 유지 관리할 뿐만 아니라 이후의 수정 사항을 파악합니다.
Cheerio를 사용하기 전에 알아두어야 할 jQuery 개념
jQuery는 오늘날 가장 널리 사용되는 자바스크립트 라이브러리 중 하나로 그 활용도가 매우 높아졌습니다. 그 목적은 문서 객체 모델(DOM)의 조작을 용이하게 하고 이벤트 처리, 애니메이션 등과 같은 다양한 요소를 제어하는 데 있습니다. 또한 웹 스크래핑을 위해 특별히 설계된 보조 도구인 Cheerio는 jQuery를 기반으로 작동하여 동일한 구문과 애플리케이션 프로그래밍 인터페이스를 유지하지만 HTML과 XML 문서를 모두 파싱하는 프로세스를 간소화합니다.
Cheerio와 jQuery를 모두 이해하고 있는 사람이라면 Cheerio를 활용하기 전에 jQuery를 사용하여 HTML 요소를 선택하는 프로세스를 숙지하는 것이 필수적이라는 사실을 잘 알고 있을 것입니다. 다행히도 jQuery는 대부분의 CSS3 선택기를 지원하므로 DOM(문서 객체 모델)에서 요소를 쉽게 추출할 수 있습니다. 예를 들어 다음 코드를 살펴보세요:
$("#container");
앞서 언급한 코드 블록은 jQuery 라이브러리를 사용하여 id 속성이 “container”인 HTML 요소를 선택합니다. 클래식 JavaScript를 사용하는 동등한 구현은 다음과 유사합니다:
document.querySelectorAll("#container");
앞서 두 코드 블록을 비교해보면 첫 번째 코드 블록이 두 번째 코드 블록에 비해 가독성이 더 뛰어나다는 것을 알 수 있습니다. 이는 코딩에서 jQuery를 활용하면 어떤 이점이 있는지 보여주는 예시입니다.
JavaScript 라이브러리 jQuery는 text() 및 html() 등 HTML 요소를 조작하기 위한 다양한 메서드를 제공합니다. 또한 부모(), 형제(), 이전(), 다음()과 같이 문서 객체 모델(DOM)을 탐색하는 데 사용할 수 있는 여러 기술이 있습니다.
수많은 Cheerio 기반 프로젝트에서 $().each() 메서드가 널리 사용되고 있습니다. 이 메서드를 사용하면 객체와 배열을 모두 반복할 수 있습니다. .each() 메서드의 구문은 다음과 같습니다:
$(<element>).each(<array or object>, callback)
앞서 언급한 배열 또는 객체 내에서 반복적으로 발생할 때마다 콜백 함수가 실행됩니다.
Cheerio로 HTML 로드하기
Cheerio를 사용하여 HTML 또는 XML 데이터 파싱을 시작하려면 cheerio.load() 함수를 사용할 수 있습니다.다음 그림을 참조하여 설명해 주세요:
const $ = cheerio.load('<html><body><h1>Hello, world!</h1></body></html>');
console.log($('h1').text())
앞서 언급한 코드는 jQuery text() 함수를 사용하여 h1 태그의 텍스트 콘텐츠를 가져옵니다. load() 메서드의 전체 구문은 다음과 같습니다:
load(content, options, mode)
콘텐츠 로딩과 관련된 매개 변수는 load() 메서드의 컨텍스트 내에서 해당 기능으로 표현됩니다. “옵션”이라고 하는 선택적으로 포함된 객체는 해당 메서드의 작동을 조작하는 역할을 합니다. 따라서 load() 메서드에는 기본 HTML 및 XML 요소(예: 머리글 및 본문 태그)가 없는 경우 이를 삽입하는 기능이 포함되어 있습니다. 그러나 이 기능을 중지하려면 “mode”라는 부울 변수 값을 false로 설정해야 합니다.
치리오로 해커 뉴스 스크래핑하기
이 작업에 사용된 소스 코드는 GitHub 리포지토리를 통해 액세스할 수 있으며 MIT 라이선스 조건에 따라 무료로 사용할 수 있습니다.
이전 학습의 정점은 기본 웹 스크레이퍼를 구성하는 데 활용됩니다. 기업가와 혁신가 모두를 위한 웹사이트 Hacker News는 빠른 로딩 속도, 사용자 친화적인 인터페이스, 광고가 없는 웹 스크래핑 실력을 보여줄 수 있는 이상적인 플랫폼을 제공합니다.
제공된 지침을 사용하려면 컴퓨터 시스템에서 Node.js와 노드 패키지 관리자를 사용해야 합니다. 시작하려면 빈 디렉토리를 생성한 다음 그 안에 package.json 파일을 만듭니다. 그런 다음 파일에 다음 JSON 콘텐츠를 삽입합니다:
{
"name": "web-scraper",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"cheerio": "^1.0.0-rc.12",
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
앞서 설명한 단계를 수행하여 터미널에 액세스하고 다음 명령을 실행합니다:
npm i
앞서 언급한 프로세스는 웹 스크래핑 도구를 구성하는 데 필요한 전제 조건을 포함해야 합니다. 이러한 구성 요소 중에는 HTML 코딩을 분석하기 위해 설계된 애플리케이션인 Cheerio, 호스팅 서비스 구축에 활용되는 플랫폼인 ExpressJS, 프로젝트 내의 변경 사항을 모니터링하고 그에 따라 서버를 재시작하는 개발 유틸리티인 Nodemon이 있습니다.
설정 및 필요한 함수 생성
index.js 파일에서 5500 또는 기타 원하는 숫자로 “PORT”로 표시되는 명명된 상수를 설정합니다. 그런 다음 Cheerio 모듈과 Express 모듈을 각각 가져옵니다.
const PORT = 5500;
const cheerio = require("cheerio");
const express = require("express");
const app = express();
다음 단계는 url, html, finishedPage의 세 가지 파라미터를 선언하는 것입니다. url에는 해커 뉴스 URL의 값이 할당됩니다.
const url = 'https://news.ycombinator.com';
let html;
let finishedPage;
function getHeader(){
return `
<div style="display:flex; flex-direction:column; align-items:center;">
<h1 style="text-transform:capitalize">Scraper News</h1>
<div style="display:flex; gap:10px; align-items:center;">
<a href="/" id="news" onClick='showLoading()'>Home</a>
<a href="/best" id="best" onClick='showLoading()'>Best</a>
<a href="/newest" id="newest" onClick='showLoading()'>Newest</a>
<a href="/ask" id="ask" onClick='showLoading()'>Ask</a>
<a href="/jobs" id="jobs" onClick='showLoading()'>Jobs</a>
</div>
<p class="loading" style="display:none;">Loading...</p>
</div>
`}
function getScript(type){
return `
<script>
document.title = "${type.substring(1)}"
window.addEventListener("DOMContentLoaded", (e) => {
let navLinks = [...document.querySelectorAll("a")];
let current = document.querySelector("#${type.substring(1)}");
document.body.style = "margin:0 auto; max-width:600px;";
navLinks.forEach(x => x.style = "color:black; text-decoration:none;");
current.style.textDecoration = "underline";
current.style.color = "black";
current.style.padding = "3px";
current.style.pointerEvents = "none";
})
function showLoading(e){
document.querySelector(".loading").style.display = "block";
document.querySelector(".loading").style.textAlign = "center";
}
</script>`
}
마지막으로 비동기적으로 작동하는 `fetchAndRenderPage()`라는 함수를 구현합니다.이 함수의 목적은 해커뉴스의 웹 페이지에서 데이터를 추출하고 Cheerio를 사용하여 처리 및 포맷을 지정한 다음 HTML 응답을 클라이언트에 전송하여 표시하는 것입니다.
async function fetchAndRenderPage(type, res) {
const response = await fetch(`${url}${type}`)
html = await response.text();
}
해커 뉴스에는 첫 페이지에 표시되는 뉴스 항목, ‘묻습니다’로 표시된 사용자가 게시한 문의, ‘베스트’로 표시된 인기 주제, ‘최신’으로 표시된 새로 게시된 게시물, ‘채용’으로 표시된 구인 정보 등 다양한 카테고리의 콘텐츠가 표시됩니다.
`fetchAndRenderPage()` 함수는 해커뉴스 웹사이트에서 지정된 카테고리에 따라 뉴스 기사 목록을 가져옵니다. 가져오기 작업에 성공하면 HTML 콘텐츠를 검색된 데이터와 연결합니다.
`apply_gradient` 함수에 다음 코드를 추가할 수 있습니다: “`python # 계산된 그라디언트로 가중치를 업데이트합니다. self.weights -= learning_rate * self.gradients def backprop(self): # 손실 함수의 기울기를 계산하기 위해 역전파를 수행합니다. # 각 가중치에 대한 손실 함수의 기울기를 계산합니다. for i in range(len(self.inputs)): d_output = (np.dot(self.input[i], self.inputs[i].T) + np.eye(self.units))**(-0.5) d_loss = -(np.dot(d_output, self.targets) + self.regularization)*(np.sqrt(2*np
res.set('Content-Type', 'text/html');
res.write(getHeader());
const $ = cheerio.load(html);
const articles = [];
let i = 1;
) 앞서 언급한 코드 블록은 애플리케이션 내에서 특정 작업을 수행하기 위해 특정 메서드를 활용하고 있습니다. set() 함수는 HTTP 헤더 필드의 값을 설정하는 데 사용됩니다. 반대로 write() 메서드는 응답 본문의 일부를 클라이언트에 디스패치하는 역할을 담당합니다. 또한 load() 함수는 HTML을 매개변수로 받아 웹페이지에 로드하는 프로세스를 실행합니다.
$('.titleline').children('a').each(function(){
let title = $(this).text();
articles.push(`<h4>${i}. ${title}</h4>`);
i++;
})
이 코드 블록의 각 반복은 지정된 HTML 요소에 포함된 텍스트 데이터를 검색하여 제목 변수에 할당합니다.
다음 단계는 스크립트의 응답으로 `articles` 배열을 채우는 것입니다. 그 다음에는 클라이언트의 브라우저로 전송할 최종 HTML 콘텐츠를 저장할 `finishedPage`라는 새 변수가 생성됩니다. 마지막으로 `write()` 메서드를 사용하여 `finishedPage` 변수를 부분적으로 배포한 후 `end()` 메서드를 사용하여 전체 전송 프로세스를 종료합니다.
articles.push(getScript(type))
finishedPage = articles.reduce((c, n) => c + n);
res.write(finishedPage);
res.end();
GET 요청을 처리할 경로 정의하기
`fetchAndRenderPage` 함수 아래에서 `express.get()` 메서드를 활용하여 다양한 종류의 게시물에 대해 고유한 경로를 설정합니다. 그런 다음 `listen()` 메서드를 사용하여 로컬 네트워크의 지정된 포트에 대한 연결에 참석합니다.
app.get('/', (req, res) => {
fetchAndRenderPage('/news', res);
})
app.get('/best', (req, res) => {
fetchAndRenderPage('/best', res);
})
app.get('/newest', (req, res) => {
fetchAndRenderPage('/newest', res);
})
app.get('/ask', (req, res) => {
fetchAndRenderPage('/ask', res);
})
app.get('/jobs', (req, res) => {
fetchAndRenderPage('/jobs', res);
})
app.listen(PORT)
코드 블록은 여러 개의 get 메서드로 구성되며, 각 메서드에는 적절한 유형과 응답 객체를 인수로 사용하여 fetchAndRenderPage 연산을 실행하는 콜백 함수가 수반됩니다.
터미널을 통해 “npm run start” 명령을 실행하면 서버가 작업을 시작할 것으로 예상됩니다. 그 후 브라우저를 사용하여 ‘localhost:5500’에서 호스팅되는 웹 페이지에 액세스하여 프로세스 결과를 확인할 수 있습니다.
외부 API 없이 해커 뉴스에서 게시물 제목을 성공적으로 검색한 것을 진심으로 축하드립니다.
웹 스크래핑으로 한 단계 더 발전하기
해커 뉴스에서 스크랩한 데이터를 활용하면 도표, 그림 삽화, 워드 클라우드라고 하는 텍스트 묘사와 같은 시각적으로 매력적인 표현을 생성할 수 있어 정보 내의 패턴과 경향을 이해하기 쉽게 파악하고 분석할 수 있습니다.
웹 스크래핑 기법을 활용하여 특정 웹 사이트에서 사용자 프로필을 추출하여 업보트 수, 게시된 댓글 및 기타 관련 기준을 포함한 다양한 측면을 고려하여 온라인 평판을 평가할 수 있습니다.