Menggunakan Rust Untuk Web Scraping - CRUDPRO

Menggunakan Rust Untuk Web Scraping

Menggunakan Rust Untuk Web Scraping

Web Scraping adalah teknik penggalian informasi dari website. Ini adalah proses otomatis untuk mengambil data dalam jumlah besar dari website, menghemat waktu dan tenaga, dan menyediakan informasi untuk berbagai keperluan.

Dalam posting ini, saya akan menunjukkan bagaimana Anda bisa menggunakan Rust untuk mengekstrak kutipan dari sebuah website.

No
Keuntungan menggunakan Rust untuk Web Scraping
1
Kinerja: Rust ialah bahasa terkompilasi yang diketik secara statis yang memberikan kinerja tinggi, menjadikannya pilihan ideal untuk Scraper web.
2
Konkurensi: Rust menyediakan dukungan konkurensi bawaan, yang membuatnya mudah untuk menangani banyak permintaan secara bersamaan, meningkatkan efisiensi Scraper web.
3
Keamanan Memori: Rust memberikan jaminan keamanan memori yang kuat, yang membantu mencegah bug terkait memori umum, seperti pengecualian penunjuk nol dan luapan buffer, membuatnya semakin aman untuk Scraper web.
4
Mudah Dipelajari: Rust memiliki sintaks yang relatif sederhana, hingga memudahkan pengembang untuk mempelajarinya, dibandingkan dengan bahasa pemrograman lainnya.
No
Rugi menggunakan Rust untuk Web Scraping
1
Curve Learning Curve: Meskipun sintaks Rust relatif sederhana, bahasanya bisa jadi menantang untuk dipelajari, terutama untuk pengembang yang baru mengenal bahasa kompilasi yang diketik secara statis.
2
Komunitas Terbatas: Sementara Rust memiliki komunitas yang berkembang, dia masih belum digunakan secara luas seperti bahasa pemrograman lainnya, yang berarti menemukan sumber daya dan dukungan bisa jadi sulit.
3
Tidak Ada Perpustakaan Scraper Web Bawaan: Rust tidak mempunyai perpustakaan bawaan untuk Scraper web, artinya pengembang harus menggunakan perpustakaan pihak ketiga, yang mungkin kurang nyaman.

Prasyarat

Sekarang, kita akan menginstal Rust, memverifikasi versi Cargo, dan menginstal tiga pustaka web scraping, reqwest, scraper, dan pilih melalui antarmuka baris perintah.

Instal rust

Untuk menginstal Rust, Anda bisa menggunakan alat Rustup, yang merupakan cara yang disarankan untuk menginstal Rust. Anda bisa menjalankan perintah berikut di terminal Anda:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Setelah menjalankan perintah ini, ikuti petunjuk di layar untuk menyelesaikan penginstalan.

Instal Kargo

Kargo adalah pengelola paket untuk Rust, dan diinstall secara otomatis saat Anda menginstal Rust. Anda bisa memeriksa apa Kargo diinstall dengan menjalankan perintah berikut ini:

cargo --version

Buat Project rust Baru

Jalankan perintah berikut di terminal Anda:

cargo new toscrape_quotes

Instal Perpustakaan Scraping Web

Untuk menginstal library Rust web scraping reqwest, scraper, dan pilih, Anda bisa menambahkan dependensi berikut ke file Kargo.toml Anda:

# Do not forget to update the dependencies section of your Cargo.toml file 

[dependencies]
csv = "1.1"
reqwest = "0.10.8"
scraper = "0.13.0"
select = "0.6.0"

Kemudian, jalankan perintah berikut di terminal Anda untuk mengunduh dan menginstal dependensi:

cd toscrape_quotes && cargo install --path .

Begitulah cara Anda bisa menginstal Rust, Kargo, dan pustaka web scraping reqwest, scraper, dan pilih melalui CLI. Dengan alat ini terinstal, Anda dapat mulai membuat aplikasi web scraping di Rust. Jika Anda tertarik untuk mengatur semuanya di Arch Linux, silakan baca salah satu postingan saya sebelumnya.

Ayo Lakukan Scraper Web. Bolehkah kita?

Toscrape.com adalah kotak scraper sand web untuk mereka yang ingin terjun ke usaha rekayasa perangkat lunak.

Tanpa menarik perhatian yang tidak diinginkan dari pengacara perusahaan platform atau organisasi perusahaan, Anda bisa menggunakannya sebagai taman bermain Anda. Ya, Anda tidak ingin melihat orang-orang itu! Beberapa memakai jas yang dipasangkan dengan Air Jordan 1 Chicago.

Kode Scraping Web rust

extern crate csv;
extern crate reqwest;
extern crate scraper;

use std::error::Error;
use std::fs::File;
use std::time::Duration;
use std::thread::sleep;

use reqwest::Client;
use reqwest::StatusCode;
use scraper::{Html, Selector};

const BASE_URL: &str = "http://quotes.toscrape.com";
const MAX_PAGE: u32 = 5;
const MAX_RETRIES: u32 = 3;
const RETRY_SLEEP_SECONDS: u64 = 2;

struct Quote {
    text: String,
    author: String,
    tags: Vec<String>,
}

fn main() -> Result<(), Box<dyn Error>> {
    let client = Client::new().timeout(Duration::from_secs(30)).build()?;
    let quotes = get_quotes(&client)?;
    write_quotes_to_csv(&quotes)?;
    Ok(())
}

fn get_quotes(client: &Client) -> Result<Vec<Quote>, Box<dyn Error>> {
    let mut quotes = Vec::new();
    for page in 1..=MAX_PAGE {
        let html = retry_get(client, &format!("{}/page/{}/", BASE_URL, page))?.text()?;
        let fragment = Html::parse_document(&html);
        let quote_selector = Selector::parse("span.text").unwrap();
        let author_selector = Selector::parse("span > small.author").unwrap();
        let tag_selector = Selector::parse("div.tags > a.tag").unwrap();

        for quote in fragment.select(&quote_selector) {
            let quote_text = quote.text().collect::<Vec<_>>()[0].trim().to_owned();
            let author = quote
                .parent()
                .unwrap()
                .select(&author_selector)
                .next()
                .unwrap()
                .text()
                .collect::<Vec<_>>()[0]
                .trim()
                .to_owned();

            let tags = quote
                .parent()
                .unwrap()
                .select(&tag_selector)
                .map(|tag| tag.text().collect::<Vec<_>>()[0].trim().to_owned())
                .collect::<Vec<_>>();

            quotes.push(Quote {
                text: quote_text,
                author,
                tags,
            });
        }
    }
    Ok(quotes)
}

fn write_quotes_to_csv(quotes: &[Quote]) -> Result<(), Box<dyn Error>> {
    let mut file = File::create("toscrape_quotes.csv")?;
    let mut writer = csv::Writer::from_writer(&mut file);

    for quote in quotes {
        writer.write_record(&[quote.text, quote.author, quote.tags.join(", ")])?;
    }
    writer.flush()?;
    Ok(())
}

fn retry_get(client: &Client, url: &str) -> Result<reqwest::Response, Box<dyn Error>> {
    let mut retries = 0;
    loop {
        match client.get(url).send() {
            Ok(res) => {
                if res.status().is_success() {
                    return Ok(res);
                } else {
                    retries += 1;
                    if retries >= MAX_RETRIES {
                        return Err(format!("GET request to {} failed with status code {:?}", url, res.status()).into());
                    }
                }
            }
            Err(err) => {
                retries += 1;
                if retries >= MAX_RETRIES {
                    return Err(format!("GET request to {} failed with error: {}", url, err).into());
                }
            }
        }
        sleep(Duration::from_secs(RETRY_SLEEP_SECONDS));
    }
}
Kode Rust di atas mencakup empat fungsi: fungsi utama, fungsi get_quotes, fungsi write_quotes_to_csv, dan fungsi retry_get.

Fungsi utama

No
Fungsi utamanya adalah titik masuk dari kode Rust, dan melakukan langkah-langkah berikut ini:
1
Membuat klien HTTP baru menggunakan reqwest::Klien.
2
Memanggil fungsi get_quotes dan melanjutkan client ke situ, yang kembalikan vector struct Quote.
3
Memanggil fungsi write_quotes_to_csv dan meneruskan vektor struktur Quote ke fungsi itu, yang menulis tanda kutip ke file.csv.
4
Mengembalikan hasil dari fungsi write_quotes_to_csv, baik Ok(()) jika semua berhasil, atau error jika terjadi kesalahan.

Inilah fungsi utamanya:

fn main() -> Result<(), Box> {
    let client = Client::new().timeout(Duration::from_secs(30)).build()?;
    let quotes = get_quotes(&client)?;
    write_quotes_to_csv(&quotes)?;
    Ok(())
}

Fungsi get_quotes

No
Fungsi get_quotes mengambil referensi ke reqwest::Klien sebagai argumen dan mengembalikan vektor struktur Quote yang diambil dari situs web "http://quotes.toscrape.com". Berikut rincian dari apa yang kami lakukan:
1
Inisialisasi vektor kosong dari struktur Quote.
2
Telusuri halaman yang akan dikorek, dari 1 hingga MAX_PAGE.
3
Untuk setiap halaman, buat permintaan GET ke URL halaman menggunakan fungsi retry_get dan ambil HTML halaman itu.
4
Parsing HTML menjadi scraper::Html fragmen.
5
Pilih teks kutipan, penulis, dan tag dari HTML menggunakan pemilih CSS.
6
Buat struktur Kutipan baru untuk setiap kutipan dan tambahkan ke vektor kutipan.
7
Kembalikan vektor kutipan.

Inilah fungsi get_quotes:

fn get_quotes(client: &Client) -> Result<Vec<Quote>, Box<dyn Error>> {
    let mut quotes = Vec::new();
    for page in 1..=MAX_PAGE {
        let html = retry_get(client, &format!("{}/page/{}/", BASE_URL, page))?.text()?;
        let fragment = Html::parse_document(&html);
        let quote_selector = Selector::parse("span.text").unwrap();
        let author_selector = Selector::parse("span > small.author").unwrap();
        let tag_selector = Selector::parse("div.tags > a.tag").unwrap();

        for quote in fragment.select(&quote_selector) {
            let quote_text = quote.text().collect::<Vec<_>>()[0].trim().to_owned();
            let author = quote
                .parent()
                .unwrap()
                .select(&author_selector)
                .next()
                .unwrap()
                .text()
                .collect::<Vec<_>>()[0]
                .trim()
                .to_owned();

            let tags = quote
                .parent()
                .unwrap()
                .select(&tag_selector)
                .map(|tag| tag.text().collect::<Vec<_>>()[0].trim().to_owned())
                .collect::<Vec<_>>();

            quotes.push(Quote {
                text: quote_text,
                author,
                tags,
            });
        }
    }
    Ok(quotes)
}

Fungsi write_quotes_to_csv

No
Fungsi write_quotes_to_csv mengambil referensi untuk mengiris struktur Quote dan menulis tanda kutip ke file .csv. Berikut rincian dari apa yang kami lakukan:
1
Buat file .csv baru dengan nama toscrape_quotes.csv.
2
Buat csv::Writer baru menggunakan peti csv.
3
Tulis catatan baru ke file .csv untuk setiap kutipan dalam slice kutipan, dengan teks kutipan, penulis, dan tag dipisahkan dengan koma.
4
Flush penulis untuk memastikan semua data ditulis ke file.
5
Kembalikan hasil operasi tulis, yaitu Ok(()) jika semuanya berhasil, atau kesalahan jika terjadi kesalahan.

Inilah fungsi write_quotes_to_csv:

fn write_quotes_to_csv(quotes: &[Quote]) -> Result<(), Box<dyn Error>> {
    let mut file = File::create("toscrape_quotes.csv")?;
    let mut writer = csv::Writer::from_writer(&mut file);

    for quote in quotes {
        writer.write_record(&[quote.text, quote.author, quote.tags.join(", ")])?;
    }
    writer.flush()?;
    Ok(())
}

Fungsi retry_get

Fungsi retry_get mengambil referensi ke reqwest::Client dan referensi ke URL string, dan membuat permintaan HTTP GET ke URL menggunakan klien. Jika permintaan gagal, fungsi mencoba ulang permintaan maksimal MAX_RETRIES kali dengan waktu tidur RETRY_SLEEP_SECONDS detik di antara setiap percobaan ulang. Berikut rincian dari apa yang kami lakukan:

  1. Inisialisasi penghitung untuk jumlah percobaan ulang.
  2. Buat permintaan GET ke URL menggunakan klien dan ambil responsnya.
  3. Jika respons berhasil (mis., kode status respons berada dalam rentang 2xx), kembalikan respons.
  4. Jika respons tidak berhasil, tingkatkan penghitung coba lagi.
  5. Jika penghitung coba lagi kurang dari MAX_RETRIES, tunggu RETRY_SLEEP_SECONDS detik dan coba lagi permintaan GET.
  6. Jika penghitung coba lagi sama dengan MAX_RETRIES, kembalikan kesalahan yang menunjukkan bahwa permintaan GET gagal.

Inilah fungsi retry_get:

fn retry_get(client: &Client, url: &str) -> Result<reqwest::Response, Box<dyn Error>> {
    let mut retries = 0;
    loop {
        match client.get(url).send() {
            Ok(res) => {
                if res.status().is_success() {
                    return Ok(res);
                } else {
                    retries += 1;
                    if retries >= MAX_RETRIES {
                        return Err(format!("GET request to {} failed with status code {:?}", url, res.status()).into());
                    }
                }
            }
            Err(err) => {
                retries += 1;
                if retries >= MAX_RETRIES {
                    return Err(format!("GET request to {} failed with error: {}", url, err).into());
                }
            }
        }
        sleep(Duration::from_secs(RETRY_SLEEP_SECONDS));
    }
}

Kesimpulannya, Rust adalah pilihan yang sangat baik untuk Scraper web karena kinerjanya yang tinggi, overhead yang rendah, dan pengelolaan memori yang aman. Kombinasi perpustakaan reqwest untuk membuat permintaan HTTP dan perpustakaan scraper untuk mem-parsing HTML memudahkan penerapan web scraping di Rust. Penggunaan penanganan kesalahan dan coba lagi dalam fungsi retry_get juga membuat kode kuat dan mampu menangani kesalahan dan waktu tunggu jaringan.

Namun, Rust adalah bahasa yang relatif baru dibandingkan dengan bahasa pemrograman web scraping yang lebih canggih seperti Python. Oleh karena itu, mungkin memiliki komunitas yang lebih kecil dan lebih sedikit perpustakaan yang tersedia. Sintaks Rust juga bisa lebih sulit bagi pemula, terutama yang terbiasa dengan bahasa pemrograman tingkat tinggi seperti Python dengan semantik dinamis.