En introduktion till webbskrapning med Cheerio

By rik

Introduktion till Webbskrapning och Cheerio

Webbskrapning är en metod för att automatiskt samla in data från webbsidor. I grunden använder webbplatser HTML för att strukturera sitt innehåll. Om denna HTML-kod är välorganiserad och semantisk, blir det enklare att extrahera relevant information. Vanligtvis använder man webbskrapning för att kontinuerligt hämta data, övervaka ändringar och spåra historik.

Förstå jQuery Innan Du Använder Cheerio

jQuery är ett populärt JavaScript-bibliotek som förenklar manipulation av Document Object Model (DOM), hantering av händelser och animationer. Cheerio är ett verktyg för webbskrapning som bygger på jQuerys grunder och använder samma syntax och API. Det gör det enkelt att analysera HTML- och XML-dokument. Innan du börjar använda Cheerio är det viktigt att förstå hur man väljer HTML-element med jQuery. jQuery stöder de flesta CSS3-selektorer, vilket gör det smidigt att välja ut element från DOM. Exempel:

 $("#container"); 

I exemplet ovan selekterar jQuery element med id ”container”. Motsvarande kod i vanlig JavaScript skulle se ut så här:

 document.querySelectorAll("#container"); 

Den första koden är tydligt enklare att läsa och skriva. jQuery erbjuder även metoder som `text()`, `html()` för att manipulera HTML-element och funktioner som `parent()`, `siblings()`, `prev()` och `next()` för att navigera genom DOM. Metoden `each()` är särskilt användbar för att iterera genom objekt och arrayer. Syntaxen ser ut så här:

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

Här körs `callback` för varje element i arrayen eller objektet.

Ladda HTML med Cheerio

För att börja tolka HTML- eller XML-data med Cheerio används metoden `cheerio.load()`. Exempel:

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

Denna kod använder `text()`-metoden för att extrahera textinnehållet från h1-elementet. Den fullständiga syntaxen för `load()` är:

 load(content, options, mode) 

`Content` refererar till HTML- eller XML-datan. `Options` är ett valfritt objekt för att anpassa beteendet. Som standard lägger `load()` till html-, head- och body-element om de saknas. Om du vill undvika detta, sätt `mode` till `false`.

Webbskrapning av Hacker News med Cheerio

Koden för det här projektet finns på GitHub och är tillgänglig under MIT-licensen.

Nu ska vi skapa en enkel webbskrapa. Hacker News är en idealisk plats för att öva på webbskrapning tack vare sin snabba laddning, enkla design och avsaknad av annonser.

Se till att du har Node.js och Node Package Manager (npm) installerat. Skapa en mapp och en `package.json`-fil med följande innehåll:

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

Kör `npm i` i terminalen för att installera nödvändiga paket: Cheerio (HTML-analys), ExpressJS (server) och Nodemon (automatisk omstart av server).

Konfiguration och Funktioner

Skapa en `index.js`-fil. Definiera en konstant `PORT` (t.ex. 5500) och importera Cheerio och Express:

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

Definiera variabler `url`, `html` och `finishedPage`. Sätt `url` till Hacker News webbadress:

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

Skapa `getHeader()`-funktionen för att generera HTML som webbläsaren ska rendera:

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

Skapa en `getScript()`-funktion som genererar JavaScript för webbläsaren:

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

Slutligen, skapa en asynkron funktion `fetchAndRenderPage()` som hämtar, analyserar och renderar en Hacker News-sida:

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

Hacker News har olika sidor: ”news” (förstasida), ”ask” (frågor), ”best” (trend), ”newest” (senaste) och ”jobs”. `fetchAndRenderPage()` hämtar inlägg baserat på typargumentet. Om hämtningen lyckas tilldelas svaret till `html`. Lägg till följande kod för att konfigurera svaret:

 res.set('Content-Type', 'text/html');
res.write(getHeader());
const $ = cheerio.load(html);
const articles = [];
let i = 1; 

Här sätts HTTP-huvudet, och den del av svaret som innehåller headern skickas. HTML:en laddas sedan med `cheerio.load()`.

Härnäst väljs alla titlar från respektive element:

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

Denna kod loopar igenom alla titelrader och extraherar textinnehållet för att skapa HTML-element. Lägg till `getScript()`-svaret i `articles`-arrayen. Skapa sedan `finishedPage` och skicka den till webbläsaren och avsluta processen:

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

Hantera GET-Förfrågningar

Använd Express `get()`-metoden för att definiera rutter för olika typer av inlägg och `listen()` för att lyssna på angiven port:

 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) 

Varje `get()`-metod anropar `fetchAndRenderPage()` med relevant typ och `res`-objekt. När du kör `npm start` startar servern. Besök sedan `localhost:5500` för att se resultatet.

Grattis! Du har framgångsrikt skrapat Hacker News och hämtat inläggstitlarna utan ett externt API.

Utveckla Webbskrapning

Med insamlade data kan du skapa visualiseringar som diagram eller grafer för att visa trender och insikter. Du kan också skrapa användarprofiler för att analysera deras rykte baserat på uppröster och kommentarer.