Увод у Веб Сцрапинг са Цхеерио

Преузимање података са веб страница, познато као веб сцрапинг, омогућава екстракцију информација са одређене веб локације. Садржај веб страница је структуриран помоћу HTML-а. Када је HTML добро организован и семантичан, знатно олакшава лоцирање релевантних података.

Веб сцрапинг се често користи за прикупљање и праћење података, као и за мониторинг промена које се дешавају током времена на тим подацима.

Кључни јКуери концепти за разумевање пре употребе Цхеерио

јКуери је популаран ЈаваСцрипт алат који поједностављује рад са Документ Објектним Моделом (ДОМ), управљање догађајима, анимацијама и другим функцијама. Цхеерио је библиотека за веб сцрапинг, изграђена на јКуери-ју, која дели синтаксу и АПИ, што олакшава анализу HTML и XML докумената.

Пре него што почнете са Цхеериом, важно је разумети како одабирати HTML елементе помоћу јКуери-ја. јКуери подржава већину CSS3 селектора, што знатно олакшава извлачење елемената из ДОМ-а. На пример:

 $("#container");

У овом примеру, јКуери бира елементе са ID-ом „контејнер“. Еквивалентна имплементација користећи стандардни ЈаваСцрипт би изгледала овако:

 document.querySelectorAll("#container");

Поредећи ова два примера кода, јасно је да је први много читљивији од другог. То је једна од предности јКуери-ја.

јКуери такође пружа корисне методе као што су `text()`, `html()` и друге, које омогућавају модификацију HTML елемената. Постоје и методе за навигацију кроз ДОМ, као што су `parent()`, `siblings()`, `prev()` и `next()`.

Метода `each()` у јКуери-ју је широко коришћена у Цхеерио пројектима. Она омогућава пролазак кроз објекте и низове. Синтакса методе `each()` је следећа:

 $(<element>).each(<array or object>, callback)

У овом случају, повратни позив се покреће за сваку итерацију низа или објекта.

Учитавање HTML-а помоћу Цхеерио

За почетак анализе HTML или XML података са Цхеерио-м, користи се метод `cheerio.load()`. На пример:

 const $ = cheerio.load('<html><body><h1>Hello, world!</h1></body></html>');
console.log($('h1').text())

Овај код користи јКуери методу `text()` за добијање текстуалног садржаја `h1` елемента. Потпуна синтакса методе `load()` изгледа овако:

 load(content, options, mode)

Параметар `content` се односи на HTML или XML податке. Параметар `options` је опциони објекат који може модификовати понашање методе. Подразумевано, метода `load()` додаје `html`, `head` и `body` елементе уколико недостају. Ако желите да онемогућите ово, параметар `mode` треба поставити на `false`.

Сцрапинг Хацкер Невс помоћу Цхеерио

Код коришћен у овом пројекту је доступан на ГитХуб спремишту и може се користити под MIT лиценцом.

Време је да спојимо научено и направимо једноставан веб сцрапер. Хацкер Невс је популарна веб локација за предузетнике и иноваторе. Такође је добра локација за вежбање веб сцрапинга, јер се брзо учитава, има једноставан интерфејс и не приказује огласе.

Уверите се да су Ноде.јс и Ноде Пацкаге Манагер инсталирани. Направите празан фолдер, затим `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-а, ЕкпрессЈС за креирање сервера и Нодемон као развојну зависност за аутоматско поновно покретање сервера при променама кода.

Припрема и креирање потребних функција

Креирајте фајл `index.js` и у њему дефинишите константу `PORT`. Подесите `PORT` на 5500 (или неки други број), а затим увезите Цхеерио и Екпресс пакете.

 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;

Сада направите функцију `getHeader()` која враћа HTML код за приказ у прегледачу.

 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="https://www.makeuseof.com/" id="news" onClick='showLoading()'>Home</a>
<a href="https://wilku.top/best" id="best" onClick='showLoading()'>Best</a>
<a href="https://wilku.top/newest" id="newest" onClick='showLoading()'>Newest</a>
<a href="https://wilku.top/ask" id="ask" onClick='showLoading()'>Ask</a>
<a href="https://wilku.top/jobs" id="jobs" onClick='showLoading()'>Jobs</a>
</div>
<p class="loading" style="display:none;">Loading...</p>
</div>
`}

Креирајте функцију `getScript()`, која враћа ЈаваСцрипт код за покретање претраживача. Обавезно проследите тип променљиве као аргумент.

 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()`. Она преузима страницу са Хацкер Невс-а, анализира је помоћу Цхеерио-а и шаље HTML назад клијенту.

 async function fetchAndRenderPage(type, res) {
const response = await fetch(`${url}${type}`)
html = await response.text();
}

На Хацкер Невс-у постоји неколико врста постова: „вести“ на главној страни, „питања“ која траже одговоре, „најбоље“ приче, „најновије“ вести и „послови“.

`fetchAndRenderPage()` преузима листу постова са Хацкер Невс-а на основу унетог типа. Ако је операција успешна, променљива `html` се везује за текст одговора.

Додајте следеће линије у функцију:

 res.set('Content-Type', 'text/html');
res.write(getHeader());

const $ = cheerio.load(html);
const articles = [];
let i = 1;

Метода `set()` поставља HTTP заглавље. Метода `write()` шаље део тела одговора. Функција `load()` узима `html` као аргумент.

Затим, додајте следеће линије да бисте селектовали децу свих елемената са класом „titleline“.

 $('.titleline').children('a').each(function(){
let title = $(this).text();
articles.push(`<h4>${i}. ${title}</h4>`);
i++;
})

Свака итерација у овом коду преузима текстуални садржај HTML елемента и чува га у променљивој `title`.

Затим, додајте одговор функције `getScript()` у низ `articles`. Креирајте променљиву `finishedPage` која ће чувати готов HTML за слање претраживачу. На крају, користите методу `write()` да пошаљете `finishedPage`, а затим `end()` да завршите процес.

 articles.push(getScript(type))
finishedPage = articles.reduce((c, n) => c + n);
res.write(finishedPage);
res.end();

Дефинисање рута за руковање GET захтевима

Одмах испод функције `fetchAndRenderPage`, користите Експресову методу `get()` да дефинишете руте за различите типове постова. Користите `listen()` да слушате везе на одређеном порту.

 app.get("https://www.makeuseof.com/", (req, res) => {
fetchAndRenderPage('/news', res);
})

app.get("https://wilku.top/best", (req, res) => {
fetchAndRenderPage("https://wilku.top/best", res);
})

app.get("https://wilku.top/newest", (req, res) => {
fetchAndRenderPage("https://wilku.top/newest", res);
})

app.get("https://wilku.top/ask", (req, res) => {
fetchAndRenderPage("https://wilku.top/ask", res);
})

app.get("https://wilku.top/jobs", (req, res) => {
fetchAndRenderPage("https://wilku.top/jobs", res);
})

app.listen(PORT)

Сваки `get` метод има функцију која позива `fetchAndRenderPage()` са одговарајућим типовима и `res` објектима.

Када отворите терминал и покренете `npm run start`, сервер ће се покренути. Можете посетити `localhost:5500` у прегледачу да видите резултате.

Честитамо, управо сте успели да преузмете наслове постова са Хацкер Невс-а без спољног API-ја.

Напредни веб сцрапинг

Са извученим подацима са Хацкер Невс-а, можете креирати разне визуелизације као што су графикони и облаци речи да бисте представили увиде и трендове у приступачном формату.

Такође можете анализирати корисничке профиле, анализирајући репутацију на основу гласова, коментара и других фактора.