Raschiare la tela con la ruggine: una guida passo passo

In questo tutorial approfondirai il web scraping di Rust. Nello specifico, imparerai:

  • Perché Rust è un ottimo linguaggio per esplorare il Web in modo efficiente.
  • Quali sono le migliori librerie di scraping in Rust.
  • Come costruire un raschietto per ruggine da zero.

Immergiamoci!


È possibile eseguire il web scraping con Rust?

TL;DR: Si, puoi! E anche Rust è una scelta efficiente!

Rust è un linguaggio di programmazione tipizzato staticamente noto per la sua attenzione alla sicurezza, alle prestazioni e alla concorrenza. Negli ultimi anni ha guadagnato popolarità per la sua alta efficienza. Ciò lo rende una scelta eccellente per una varietà di applicazioni, incluso il web scraping.

Nel dettaglio, Rust offre funzionalità utili per le attività di scraping dei dati online. Ad esempio, il suo modello di concorrenza affidabile consente di eseguire più richieste web contemporaneamente. Questo è il motivo per cui Rust è un linguaggio versatile per estrarre in modo efficiente grandi volumi di dati da più siti Web.

Oltre a ciò, l’ecosistema Rust include client HTTP e librerie di parsing HTML che semplificano il recupero delle pagine web e l’estrazione dei dati. Esploriamo alcuni dei più popolari!


Le migliori librerie di web scraping di Rust

Ecco un elenco di alcune delle migliori librerie di web scraping per Rust:

  • rich: una potente libreria client HTTP per Rust. Fornisce un’API semplice ed efficiente per effettuare richieste HTTP. Grazie ad esso, puoi scaricare pagine web, gestire cookie e personalizzare intestazioni, rendendolo una libreria essenziale per recuperare contenuti web nel tuo progetto di scraping.
  • raschietto: una libreria Rust che semplifica l’analisi HTML e l’estrazione dei dati. Ti consente di attraversare e manipolare documenti HTML tramite selettori CSS attraverso metodi integrati.
  • ruggine-cromo senza testa: una libreria Rust che espone un’API di alto livello per il controllo delle istanze headless di Chrome tramite il protocollo DevTools. Puoi considerarlo l’equivalente Rust di Puppeteer. Si tratta di uno strumento indispensabile per affrontare le attività di scraping che coinvolgono pagine dinamiche che richiedono il rendering JavaScript o l’automazione del browser.

Prerequisiti

Per seguire questo tutorial di Rust sul web scraping, devi avere Rust installato sul tuo computer. Avvia il comando seguente nel tuo terminale per verificare che:

rustc --version

Se il risultato è il seguente, sei pronto per partire:

rustc 1.73.0 (cc66ad468 2023-10-03)

Se termina con un errore, devi installare Rust. Scarica il programma di installazione dal sito ufficiale e segui le istruzioni. Questo imposterà:

  • ruggine: il gestore della catena di strumenti di Rust
  • cargo: il gestore dei pacchetti Rust.

Sai che è necessario un IDE per programmare in Rust. Visual Studio Code con l’estensione ruggine-analyzer installata è una soluzione gratuita e affidabile.


Costruisci un raschietto Web in Rust

In questa sezione passo dopo passo, vedrai come costruire un web scraper Rust. Codificherai uno script automatizzato in grado di recuperare automaticamente i dati dalla sandbox di scraping delle quotazioni. L’obiettivo del processo di web scraping di Rust sarà:

  1. Seleziona gli elementi HTML di citazione dalla pagina.
  2. Estrai i dati da loro.
  3. Converti i dati raccolti in un formato facile da esplorare, come CSV.

Al momento della stesura di questo articolo, ecco come appare il sito di destinazione:

Convertire i dati raccolti

Segui le istruzioni seguenti e scopri come eseguire il web scraping in Rust!

Passaggio 1: imposta un progetto in Rust

È ora di inizializzare il tuo progetto di web scraper Rust. Apri il terminale nella cartella in cui desideri inserire il tuo progetto ed esegui il comando cargo di seguito:

cargo new rust_web_scraper

Apparirà una directory ruggine_web_scraper. Aprilo e vedrai:

  • toml: il file manifest che contiene le dipendenze del progetto.
  • src/: la cartella contenente i file Rust.

Apri la cartella ruggine_web_scraper nel tuo IDE. Noterai che il file main.rs all’interno della directory src contiene:

fn main() {

println!("Hello, world!");

}

Questo è l’aspetto dello script Rust più semplice. La funzione main() rappresenta il punto di ingresso di qualsiasi applicazione Rust.

Perfetto, verifica che il tuo script funzioni!

Nel terminale del tuo IDE, esegui il comando seguente per compilare la tua app Rust:

cargo build

Questo dovrebbe creare un file binario nella cartella di destinazione.

Ora puoi eseguire l’eseguibile binario con:

cargo run

Se tutto va come previsto, dovrebbe essere stampato nel terminale:

Hello, World!

Fantastico, ora hai un progetto Rust funzionante! In questo momento, il tuo raschietto stampa semplicemente “Hello, World!” ma presto conterrà una logica raschiante.

Passaggio 2: installa le dipendenze del progetto

Prima di installare qualsiasi pacchetto, devi capire quali librerie di web scraping Rust si adattano meglio ai tuoi obiettivi. Per fare ciò, apri il sito di destinazione nel tuo browser. Fare clic con il tasto destro e selezionare l’opzione “Ispeziona” per aprire DevTools. Quindi, raggiungi la scheda “Rete”, ricarica la pagina e dai un’occhiata alla sezione “Recupera/XHR”.

Installa le dipendenze del progetto

Come puoi vedere, la pagina web non esegue alcuna richiesta AJAX. In altre parole, non recupera i dati dinamicamente sul client. Si tratta quindi di una pagina statica il cui contenuto HTML contiene già tutti i dati.

Di conseguenza, non è necessaria una libreria con funzionalità di browser headless per eseguire il web scraping su di essa. Puoi comunque utilizzare Headless Chrome, ma ciò introdurrebbe solo un sovraccarico in termini di prestazioni. Ecco perché dovresti optare per:

  • reqwest: come client HTTP per recuperare i documenti HTML associati alle pagine di destinazione.
  • raschietto: come parser HTML per analizzare il contenuto HTML e recuperare i dati da esso.

Aggiungi reqwest e scraper alle dipendenze del tuo progetto con:

cargo add scraper reqwest --features "reqwest/blocking"

Il comando aggiornerà di conseguenza il file Cargo.toml.

Ben fatto! Ora hai tutto il necessario per eseguire lo scraping dei dati in Rust!

Passaggio 3: scarica la pagina di destinazione

Utilizza il client HTTP di blocco di reqwest per scaricare il documento HTML della pagina di destinazione:

let response = reqwest::blocking::get("https://quotes.toscrape.com/");

let html = response.unwrap().text().unwrap();

Dietro le quinte, get() esegue una richiesta HTTP GET sincrona all’URL passato come parametro. L’esecuzione dello script verrà interrotta finché il server non risponde.

Per estrarre l’HTML grezzo come stringa dalla risposta, devi chiamare unwrap() due volte per:

  1. Scarta l’oggetto Risultato memorizzato nella variabile di risposta. Se la richiesta ha esito positivo, riceverai la risposta restituita dal server. Altrimenti, ciò causerà il panico da Rust.
  2. Scarta il contenuto testuale per accedere al contenuto HTML.

Passaggio 4: analizzare il documento HTML

Ora che hai il contenuto HTML della pagina di destinazione memorizzato in una stringa, puoi alimentarlo allo scraper:

let document = scraper::Html::parse_document(&html)

L’oggetto documento espone l’API di estrazione dati esposta dal parser HTML.

Il tuo file main.rs ora dovrebbe apparire come segue:

fn main() {

// download the HTML document associated with the target page

let response = reqwest::blocking::get("https://quotes.toscrape.com/");

// extract the raw HTML from the response

let html = response.unwrap().text().unwrap();

// parse the HTML content

let document = scraper::Html::parse_document(&html);

// scraping logic...

}

Passaggio 5: ispeziona il contenuto della pagina

È ora di analizzare la struttura dell’URL di destinazione per ideare un’efficace strategia di recupero dei dati.

Apri Quotes To Scrape nel tuo browser. Vedrai un elenco di citazioni. Fare clic con il tasto destro su uno di questi elementi e selezionare “Ispeziona”. I DevTools del tuo browser si apriranno come di seguito:

Citazioni da raschiare

Lì puoi notare che ogni scheda di preventivo è un nodo HTML .quote che contiene:

  1. Un elemento .text che memorizza il testo della citazione.
  2. Un elemento .author contenente il nome dell’autore.
  3. Molti elementi .tag, ciascuno dei quali visualizza un singolo tag.

Le note precedenti contengono tutti i selettori CSS necessari per selezionare gli elementi DOM desiderati. Ora devi usarli nel tuo codice per eseguire il web scraping di Rust!

Passaggio 6: implementare lo scraping dei dati

Prima di iniziare, hai bisogno di una struttura dati personalizzata in cui archiviare i dati raschiati. Aggiungi le seguenti righe sopra il tuo file main.rs per definire una nuova struttura:

struct Quote {

quote: Option<String>,

author: Option<String>,

tags: Vec<String>,

}

Poiché la pagina contiene diverse virgolette, istanziare un Vec di oggetti Quote in main():

let mut quotes: Vec<Quote> = Vec::new();

Alla fine dello script, le virgolette conterranno tutti i dati raschiati.

Scopri come popolare l’array!

Definire un oggetto Selettore CSS nello scraper come segue:

let html_quote_selector = scraper::Selector::parse(".quote").unwrap();

Successivamente, utilizza il metodo select() da applicare alla pagina e recuperare gli elementi HTML desiderati:

let html_quotes = document.select(&html_quote_selector);

Ora puoi eseguire l’iterazione su ciascun elemento preventivo ed estrarre da esso i dati di interesse con:

for html_quote in html_quotes {

let quote_selector = scraper::Selector::parse(".text").unwrap();

let quote = html_quote

.select(&quote_selector)

.next()

.map(|element| element.text().collect::<String>());




let author_selector = scraper::Selector::parse(".author").unwrap();

let author = html_quote

.select(&author_selector)

.next()

.map(|element| element.text().collect::<String>());




let tags_selector = scraper::Selector::parse(".tag").unwrap();

let tags = html_quote

.select(&tags_selector)

.map(|element| element.text().collect::<String>())

.collect();




// create a new quote object with the scraped data

// and store it in the list

let quote_obj = Quote {

quote,

author,

tags,

};

quotes.push(quote_obj);

}

Le prime righe applicano lo stesso approccio visto sopra. Definiscono un oggetto selettore CSS e lo applicano all’elemento HTML quote. Poiché select() restituisce diversi elementi, puoi utilizzare next() per ottenere il primo. Quindi, il metodo text() ti dà accesso al suo contenuto testuale.

Una volta ottenuti i dati di scraping, resta solo da popolare un nuovo oggetto Quote e aggiungerlo all’array.

Fantastico! Hai appena imparato come eseguire il web scraping in Rust!

Passaggio 7: aggiungi la logica di scansione

Hai appena estratto i dati da una singola pagina, ma non dimenticare che l’elenco delle citazioni è composto da più pagine. In particolare ogni pagina è dotata di un pulsante “Avanti →” con il collegamento alla pagina seguente:

Aggiungi la logica di scansione

Questo vale per tutte le pagine tranne l’ultima:

Questo vale per tutte le pagine tranne l'ultima

Per eseguire la scansione web e raccogliere dati da ciascuna pagina, è necessario:

  1. Gratta una pagina.
  2. Controlla se l’elemento “Avanti →” è presente nella pagina.
  3. In tal caso, segui il suo URL e ripeti il ​​ciclo per una nuova pagina. Altrimenti, interrompi la logica di scansione.

Implementa l’algoritmo di cui sopra in Rust come di seguito:

// the URL of the first page to scrape

let mut url = "https://quotes.toscrape.com/".to_owned();

loop {

// download the HTML document associated with the target page

let response = reqwest::blocking::get(url);




// parsing and scraping logic...




// select the "Next ->" element

let next_page_element_selector = scraper::Selector::parse(".next").unwrap();

let next_page_element = document.select(&next_page_element_selector).next();




// if this is not the last page

if next_page_element.is_some() {

// retrieve the relative URL to the next page

let next_page_link_selector = scraper::Selector::parse("a").unwrap();

let partial_url = next_page_element

.unwrap()

.select(&next_page_link_selector)

.next()

.and_then(|a| a.value().attr("href"))

.map(str::to_owned)

.unwrap();




// the next page to scrape

url = format!("https://quotes.toscrape.com{partial_url}");

} else {

break;

}

}

Meraviglioso! La logica di scraping dei dati di Rust è completa!

Passaggio 8: esporta i dati estratti in CSV

I dati raschiati sono ora archiviati in oggetti Rust. Devi convertirlo in un formato diverso per renderlo più facile da leggere e utilizzare da altri membri del tuo team. Scopri come esportare i dati raccolti in un file CSV.

Potresti creare un file CSV e compilarlo con Vanilla Rust, ma la libreria CSV rende tutto più semplice. Installalo con:

carico aggiungi csv

Ora puoi convertire le virgolette in un file CSV con solo poche righe di codice:

// initialize the CSV output file

let path = std::path::Path::new("quotes.csv");




let mut writer = csv::Writer::from_path(path).unwrap();

// append the header to the CSV

writer.write_record(&("quote", "author", "tags")).unwrap();




// populate the CSV file

for quote_obj in quotes {

// if the "quote" and "author" fields are not None

if let (Some(quote), Some(author)) = (quote_obj.quote, quote_obj.author) {

let tags = quote_obj.tags.join("; ");

writer.write_record(&(quote, author, tags)).unwrap();

}

}

// free up the writer resources

writer.flush().unwrap();

The above snippet initializes a CSV file with the header row. Then, it iterates over the array of quotes, converts each element to records in CSV formats, and appends it to the output file.

Passaggio 9: metti tutto insieme

Ecco il codice completo del tuo Raschiaruggine:

// define a custom data structure

// where to store the scraped data

struct Quote {

quote: Option<String>,

author: Option<String>,

tags: Vec<String>,

}




fn main() {

// initialize the vector that will store the objects

// with the scraped quotes

let mut quotes: Vec<Quote> = Vec::new();




// the URL of the first page to scrape

let mut url = "https://quotes.toscrape.com/".to_owned();




loop {

// download the HTML document associated with the target page

let response = reqwest::blocking::get(url);




// extract the raw HTML from the response

let html = response.unwrap().text().unwrap();

// parse the HTML content

let document = scraper::Html::parse_document(&html);




// select all quote HTML elements on the page

let html_quote_selector = scraper::Selector::parse(".quote").unwrap();

let html_quotes = document.select(&html_quote_selector);




// iterate over each HTML quote to extract data

for html_quote in html_quotes {

// data scraping logic

let quote_selector = scraper::Selector::parse(".text").unwrap();

let quote = html_quote

.select(&quote_selector)

.next()

.map(|element| element.text().collect::<String>());




let author_selector = scraper::Selector::parse(".author").unwrap();

let author = html_quote

.select(&author_selector)

.next()

.map(|element| element.text().collect::<String>());




let tags_selector = scraper::Selector::parse(".tag").unwrap();

let tags = html_quote

.select(&tags_selector)

.map(|element| element.text().collect::<String>())

.collect();




// create a new quote object with the scraped data

// and store it in the list

let quote_obj = Quote {

quote,

author,

tags,

};

quotes.push(quote_obj);

}




// select the "Next ->" element

let next_page_element_selector = scraper::Selector::parse(".next").unwrap();

let next_page_element = document.select(&next_page_element_selector).next();




// if this is not the last page

if next_page_element.is_some() {

// retrieve the relative URL to the next page

let next_page_link_selector = scraper::Selector::parse("a").unwrap();

let partial_url = next_page_element

.unwrap()

.select(&next_page_link_selector)

.next()

.and_then(|a| a.value().attr("href"))

.map(str::to_owned)

.unwrap();




// the next page to scrape

url = format!("https://quotes.toscrape.com{partial_url}");

} else {

break;

}

}




// initialize the CSV output file

let path = std::path::Path::new("quotes.csv");




let mut writer = csv::Writer::from_path(path).unwrap();

// append the header to the CSV

writer.write_record(&("quote", "author", "tags")).unwrap();




// populate the CSV file

for quote_obj in quotes {

// if the "quote" and "author" fields are not None

if let (Some(quote), Some(author)) = (quote_obj.quote, quote_obj.author) {

let tags = quote_obj.tags.join("; ");

writer.write_record(&(quote, author, tags)).unwrap();

}

}




// free up the writer resources

writer.flush().unwrap();

}

Sorprendente! In circa 100 righe di codice puoi creare un data scraper in Rust!

Compilare la domanda con:

cargo build

Quindi eseguilo con:

cargo run

Sii paziente mentre il raschietto Rust recupera i dati da ogni pagina. Al termine, un file quotes.csv apparirà nella cartella principale del tuo progetto. Aprilo e dovresti vedere i seguenti dati:

Raschietto per ruggine

Et voilà! Hai iniziato con dati non strutturati nelle pagine online e ora li hai in un pratico file CSV!


Conclusione

In questa guida hai visto perché Rust è un linguaggio efficace per il web scraping. Hai anche avuto l’opportunità di esplorare alcune delle sue migliori librerie di scraping. Quindi, hai imparato come usarli per creare un raschietto Rust in grado di estrarre dati da un obiettivo del mondo reale. Come hai visto, il web scraping con Rust è semplice e richiede solo poche righe di codice.

Il problema principale è rappresentato dai sistemi anti-bot e anti-scraping che i siti web adottano per proteggere i propri dati. Queste soluzioni possono rilevare e bloccare il tuo script di scraping. Fortunatamente, Bright Data ha una serie di soluzioni per te:

  • IDE di Web Scraper: un IDE cloud per creare web scraper in grado di bypassare ed evitare automaticamente eventuali blocchi.
  • Browser di raschiatura: un browser controllabile basato su cloud che offre funzionalità di rendering JavaScript mentre gestisce CAPTCHA, impronte digitali del browser, tentativi automatizzati e altro ancora. Si integra con le librerie dei browser di automazione più popolari, come Playwright e Puppeteer.
  • Sblocco Web: un’API di sblocco in grado di restituire senza problemi l’HTML grezzo di qualsiasi pagina, aggirando qualsiasi misura anti-scraping.

Non vuoi assolutamente occuparti del web scraping ma sei comunque interessato ai dati online? Esplora i set di dati pronti all’uso di Bright Data!