Úvod do Web Scraping s Cheerio

Web scraping je technika, která umožňuje získat data z konkrétní webové stránky. Webové stránky používají HTML k popisu svého obsahu. Pokud je HTML čistý a sémantický, je snadné jej použít k nalezení užitečných dat.

K získávání a sledování dat a sledování budoucích změn obvykle použijete webový škrabák.

Koncepty jQuery, které stojí za to znát, než použijete Cheerio

jQuery je jedním z nejpopulárnějších balíčků JavaScriptu. Usnadňuje práci s objektovým modelem dokumentu (DOM), zpracovává události, animace a další. Cheerio je balíček pro web scraping, který staví na jQuery – sdílí stejnou syntaxi a API a zároveň usnadňuje analýzu HTML nebo XML dokumentů.

Než se naučíte používat Cheerio, je důležité vědět, jak vybrat prvky HTML pomocí jQuery. Naštěstí jQuery podporuje většinu selektorů CSS3, což usnadňuje zachycení prvků z DOM. Podívejte se na následující kód:

 $("#container");

Ve výše uvedeném bloku kódu jQuery vybere prvky s id „container“. Podobná implementace pomocí běžného starého JavaScriptu by vypadala asi takto:

 document.querySelectorAll("#container");

Při porovnání posledních dvou bloků kódu můžete vidět, že první blok kódu je mnohem snáze čitelný než druhý. To je krása jQuery.

jQuery má také užitečné metody jako text(), html() a další, které umožňují manipulovat s prvky HTML. Existuje několik metod, které můžete použít k procházení DOM, jako parent(), siblings(), prev() a next().

Metoda every() v jQuery je velmi populární v mnoha projektech Cheerio. Umožňuje vám iterovat objekty a pole. Syntaxe metody every() vypadá takto:

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

Ve výše uvedeném bloku kódu se zpětné volání spustí pro každou iteraci pole nebo argumentu objektu.

Načítání HTML pomocí Cheerio

Chcete-li začít analyzovat data HTML nebo XML pomocí Cheerio, můžete použít metodu cheerio.load(). Podívejte se na tento příklad:

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

Tento blok kódu používá metodu jQuery text() k načtení textového obsahu prvku h1. Úplná syntaxe metody load() vypadá takto:

 load(content, options, mode)

Parametr content odkazuje na skutečná data HTML nebo XML, která předáváte metodě load(). options je volitelný objekt, který může upravit chování metody. Ve výchozím nastavení zavádí metoda load() prvky html, head a body, pokud chybí. Pokud chcete toto chování zastavit, ujistěte se, že jste režim nastavili na hodnotu false.

Škrábání Hacker News S Cheerio

Kód použitý v tomto projektu je k dispozici v a úložiště GitHub a můžete jej používat zdarma pod licencí MIT.

Je čas spojit vše, co jste se doposud naučili, a vytvořit jednoduchý webový škrabák. Hacker News je oblíbený web pro podnikatele a inovátory. Je to také perfektní webová stránka, na které můžete využít své dovednosti v oblasti škrábání webu, protože se načítá rychle, má velmi jednoduché rozhraní a nezobrazuje žádné reklamy.

Ujistěte se, že máte na počítači spuštěn Node.js a Node Package Manager. Vytvořte prázdnou složku, poté soubor package.json a do souboru přidejte následující 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"
  }
}

Poté otevřete terminál a spusťte:

 npm i

Tím by se měly nainstalovat potřebné závislosti, které potřebujete k sestavení škrabky. Tyto balíčky zahrnují Cheerio pro analýzu HTML, ExpressJS pro vytvoření serveru a – jako vývojovou závislost – Nodemon, nástroj, který naslouchá změnám v projektu a automaticky restartuje server.

Nastavení věcí a vytváření nezbytných funkcí

Vytvořte soubor index.js a v tomto souboru vytvořte konstantní proměnnou s názvem „PORT“. Nastavte PORT na 5500 (nebo jakékoli číslo, které si vyberete), poté importujte balíčky Cheerio a Express.

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

Dále definujte tři proměnné: url, html a finishPage. Nastavte adresu URL na adresu URL Hacker News.

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

Nyní vytvořte funkci nazvanou getHeader(), která vrátí nějaké HTML, které by měl prohlížeč vykreslit.

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

Vytvoří další funkci getScript(), která vrátí nějaký JavaScript, aby prohlížeč mohl spustit. Ujistěte se, že předáte typ proměnné jako argument, když ji voláte.

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

Nakonec vytvořte asynchronní funkci s názvem fetchAndRenderPage(). Tato funkce dělá přesně to, co si myslíte – seškrábe stránku v Hacker News, analyzuje a naformátuje ji pomocí Cheerio a poté pošle nějaké HTML zpět klientovi k vykreslení.

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

Na Hacker News jsou k dispozici různé typy příspěvků. Jsou zde „zprávy“, což je materiál na titulní stránce, příspěvky hledající odpovědi od ostatních členů Hacker News mají štítek „zeptat se“. Populární příspěvky mají štítek „nejlepší“, nejnovější příspěvky mají štítek „nejnovější“ a příspěvky týkající se volných pracovních míst mají štítek „práce“.

fetchAndRenderPage() načte seznam příspěvků ze stránky Hacker News na základě typu, který zadáte jako argument. Pokud je operace načtení úspěšná, funkce sváže proměnnou html s textem odpovědi.

Dále do funkce přidejte následující řádky:

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

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

Ve výše uvedeném bloku kódu nastavuje metoda set() pole záhlaví HTTP. Metoda write() je zodpovědná za odeslání části těla odpovědi. Funkce load() bere jako argument html.

Dále přidejte následující řádky a vyberte příslušné potomky všech prvků s třídou „titleline“.

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

V tomto bloku kódu každá iterace načte textový obsah cílového prvku HTML a uloží jej do proměnné title.

Dále vložte odpověď z funkce getScript() do pole článků. Poté vytvořte proměnnou finishPage, která bude obsahovat hotový kód HTML k odeslání do prohlížeče. Nakonec použijte metodu write() k odeslání hotové stránky jako kusu a ukončete proces odezvy pomocí metody end().

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

Definování tras pro zpracování požadavků GET

Přímo pod funkcí fetchAndRenderPage použijte metodu express get() k definování příslušných tras pro různé typy příspěvků. Poté použijte metodu naslouchání k naslouchání připojení k určenému portu ve vaší místní síti.

 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)

Ve výše uvedeném bloku kódu má každá metoda get funkci zpětného volání, která volá funkci fetchAndRenderPage předávání příslušných typů a objektů res.

Když otevřete terminál a spustíte npm, spustí se spuštění. Server by se měl spustit, poté můžete ve svém prohlížeči navštívit localhost:5500 a zobrazit výsledky.

Gratulujeme, právě se vám podařilo seškrábat Hacker News a načíst názvy příspěvků bez potřeby externího rozhraní API.

Vezmeme věci dále pomocí škrábání webu

S daty, která získáte z Hacker News, můžete vytvářet různé vizualizace, jako jsou tabulky, grafy a mračna slov, abyste mohli prezentovat statistiky a trendy ve srozumitelnějším formátu.

Můžete také seškrábat uživatelské profily a analyzovat reputaci uživatelů na platformě na základě faktorů, jako jsou obdržené hlasy, komentáře a další.