Wprowadzenie do skrobania stron internetowych za pomocą Cheerio

Web scraping to technika umożliwiająca pozyskanie danych z konkretnej strony internetowej. Witryny używają HTML do opisywania swoich treści. Jeśli kod HTML jest przejrzysty i semantyczny, łatwo go użyć do zlokalizowania przydatnych danych.

Zwykle będziesz używać skrobaka internetowego do uzyskiwania i monitorowania danych oraz śledzenia przyszłych zmian w nich.

Koncepcje jQuery, które warto znać przed użyciem Cheerio

jQuery to jeden z najpopularniejszych istniejących pakietów JavaScript. Ułatwia pracę z Document Object Model (DOM), obsługą zdarzeń, animacjami i nie tylko. Cheerio to pakiet do skrobania stron internetowych, który opiera się na jQuery — ma tę samą składnię i interfejs API, a jednocześnie ułatwia analizowanie dokumentów HTML lub XML.

Zanim nauczysz się korzystać z Cheerio, ważne jest, aby wiedzieć, jak wybierać elementy HTML za pomocą jQuery. Na szczęście jQuery obsługuje większość selektorów CSS3, co ułatwia pobieranie elementów z modelu DOM. Spójrz na następujący kod:

 $("#container");

W powyższym bloku kodu jQuery wybiera elementy o identyfikatorze „kontener”. Podobna implementacja wykorzystująca zwykły stary JavaScript wyglądałaby mniej więcej tak:

 document.querySelectorAll("#container");

Porównując dwa ostatnie bloki kodu, widać, że poprzedni blok kodu jest znacznie łatwiejszy do odczytania niż drugi. Na tym polega piękno jQuery.

jQuery ma również przydatne metody, takie jak text(), html() i inne, które umożliwiają manipulowanie elementami HTML. Istnieje kilka metod, których można użyć do przechodzenia przez DOM, na przykład parent(), rodzeństwo(), prev() i next().

Metoda each() w jQuery jest bardzo popularna w wielu projektach Cheerio. Pozwala iterować po obiektach i tablicach. Składnia metody each() wygląda następująco:

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

W powyższym bloku kodu wywołanie zwrotne jest uruchamiane dla każdej iteracji argumentu tablicy lub obiektu.

Ładowanie HTML za pomocą Cheerio

Aby rozpocząć analizowanie danych HTML lub XML za pomocą Cheerio, możesz użyć metody cheerio.load() . Spójrz na ten przykład:

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

Ten blok kodu wykorzystuje metodę jQuery text() do pobierania zawartości tekstowej elementu h1. Pełna składnia metody load() wygląda następująco:

 load(content, options, mode)

Parametr content odnosi się do rzeczywistych danych HTML lub XML przekazywanych metodą load() . options to opcjonalny obiekt, który może modyfikować zachowanie metody. Domyślnie metoda load() wprowadza elementy html, head i body, jeśli ich brakuje. Jeśli chcesz zatrzymać to zachowanie, upewnij się, że ustawiłeś tryb na fałsz.

Skrobanie wiadomości hakerów za pomocą Cheerio

Kod użyty w tym projekcie jest dostępny w formacie Repozytorium GitHub i jest darmowy do użytku na licencji MIT.

Czas połączyć wszystko, czego nauczyłeś się do tej pory i stworzyć prosty web scraper. Hacker News to popularna strona internetowa dla przedsiębiorców i innowatorów. Jest to również idealna strona internetowa, na której możesz wykorzystać swoje umiejętności przeglądania stron internetowych, ponieważ ładuje się szybko, ma bardzo prosty interfejs i nie wyświetla żadnych reklam.

Upewnij się, że na komputerze działa Node.js i Menedżer pakietów węzłów. Utwórz pusty folder, a następnie plik package.json i dodaj następujący kod JSON w pliku:

 {
  "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"
  }
}

Po wykonaniu tej czynności otwórz terminal i uruchom:

 npm i

To powinno zainstalować niezbędne zależności potrzebne do zbudowania skrobaka. Pakiety te obejmują Cheerio do analizowania HTML, ExpressJS do tworzenia serwera oraz — jako zależność programistyczną — Nodemon, narzędzie, które nasłuchuje zmian w projekcie i automatycznie restartuje serwer.

Konfigurowanie rzeczy i tworzenie niezbędnych funkcji

Utwórz plik index.js iw tym pliku utwórz stałą zmienną o nazwie „PORT”. Ustaw PORT na 5500 (lub dowolną wybraną liczbę), a następnie zaimportuj odpowiednio pakiety Cheerio i Express.

 const PORT = 5500;
const cheerio = require("cheerio");
const express = require("express");
const app = express();

Następnie zdefiniuj trzy zmienne: url, html i readyPage. Ustaw adres URL na adres URL Hacker News.

 const url="https://news.ycombinator.com";
let html;
let finishedPage;

Teraz utwórz funkcję o nazwie getHeader(), która zwraca kod HTML, który przeglądarka powinna wyświetlić.

 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>
`}

Utwórz kolejną funkcję getScript(), która zwraca trochę kodu JavaScript do uruchomienia przeglądarki. Upewnij się, że przekazujesz typ zmiennej jako argument podczas jej wywoływania.

 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>`
}

Na koniec utwórz funkcję asynchroniczną o nazwie fetchAndRenderPage(). Ta funkcja robi dokładnie to, o czym myślisz — zeskrobuje stronę w Hacker News, analizuje ją i formatuje za pomocą Cheerio, a następnie wysyła kod HTML z powrotem do klienta w celu renderowania.

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

W Hacker News dostępne są różne rodzaje postów. Są „wiadomości”, które są na pierwszej stronie, posty szukające odpowiedzi od innych członków Hacker News mają etykietę „zapytaj”. Popularne posty mają etykietę „najlepsze”, najnowsze posty mają etykietę „najnowsze”, a posty dotyczące wolnych miejsc pracy mają etykietę „prace”.

fetchAndRenderPage() pobiera listę postów ze strony Hacker News na podstawie typu podanego jako argument. Jeśli operacja pobierania zakończy się pomyślnie, funkcja wiąże zmienną html z tekstem odpowiedzi.

Następnie dodaj następujące linie do funkcji:

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

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

W powyższym bloku kodu metoda set() ustawia pole nagłówka HTTP. Metoda write() odpowiada za wysłanie fragmentu treści odpowiedzi. Funkcja load() przyjmuje jako argument html.

Następnie dodaj następujące wiersze, aby wybrać odpowiednie elementy podrzędne wszystkich elementów z klasą „tytuł”.

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

W tym bloku kodu każda iteracja pobiera treść tekstową docelowego elementu HTML i zapisuje ją w zmiennej tytułowej.

Następnie umieść odpowiedź z funkcji getScript() w tablicy artykułów. Następnie utwórz zmienną readyPage, która będzie przechowywać gotowy kod HTML do wysłania do przeglądarki. Na koniec użyj metody write() , aby wysłać finishPage jako porcję i zakończyć proces odpowiedzi metodą end() .

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

Definiowanie tras do obsługi żądań GET

Bezpośrednio pod funkcją fetchAndRenderPage użyj metody express get() do zdefiniowania odpowiednich tras dla różnych typów postów. Następnie użyj metody nasłuchiwania, aby nasłuchiwać połączeń z określonym portem w sieci lokalnej.

 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)

W powyższym bloku kodu każda metoda get ma funkcję wywołania zwrotnego, która wywołuje funkcję fetchAndRenderPage, przekazując odpowiednie typy i obiekty res.

Kiedy otworzysz terminal i uruchomisz npm run start. Serwer powinien się uruchomić, a następnie możesz odwiedzić localhost:5500 w przeglądarce, aby zobaczyć wyniki.

Gratulacje, właśnie udało Ci się zeskrobać Hacker News i pobrać tytuły postów bez potrzeby korzystania z zewnętrznego API.

Idąc dalej dzięki skrobaniu stron internetowych

Dzięki danym zebranym z Hacker News możesz tworzyć różne wizualizacje, takie jak wykresy, wykresy i chmury słów, aby przedstawiać spostrzeżenia i trendy w bardziej przystępnym formacie.

Możesz także zeskrobać profile użytkowników, aby przeanalizować reputację użytkowników na platformie na podstawie takich czynników, jak otrzymane pozytywne głosy, dodane komentarze i inne.