Beranda BlogPengikisan web Pengikisan web dengan Ruby

Pengikisan web dengan Ruby

oleh Kadek

Di bawah Pengikisan web adalah ekstraksi otomatis informasi dari situs web. Ini adalah teknik canggih yang memungkinkan pengembang mengumpulkan data dari situs web dengan cepat dan mudah tanpa harus memasukkan atau mengunduhnya secara manual. Pengikisan web dapat digunakan untuk berbagai tujuan, seperti melacak harga produk, mengumpulkan informasi kontak, atau menganalisis tren di situs media sosial.

Salah satu bahasa pemrograman paling populer untuk web scraping adalah Ruby karena open source, fleksibilitas, dan kemudahan penggunaannya. Kita telah membahas web scraping dengan Python, C#, NodeJS dan R, namun pada artikel ini kita akan melihat Ruby. Dengan Ruby, Anda dapat menulis skrip kompleks yang mengotomatiskan seluruh proses pengumpulan data - mulai dari mengakses halaman situs web hingga menguraikan informasi yang relevan (seperti alamat email). Ruby juga memiliki berbagai perpustakaan tambahan yang dirancang khusus untuk tujuan web scraping. Di Github Anda akan menemukan banyak perpustakaan untuk dipilih. Namun, dalam artikel ini kami hanya akan fokus pada yang paling luas dan terkenal.

Mempersiapkan web scraping dengan Ruby

Sebelum kita mulai membuat web scraper berbasis Ruby, kita perlu mempersiapkan lingkungan, mempertimbangkan dan menginstal perpustakaan yang diperlukan. Pertama persiapkan lingkungan dan instal Ruby. Kami kemudian melihat perpustakaan dan menginstalnya.

Instal lingkungan

Website resmi Ruby menyediakan perintah untuk menginstal Ruby di semua sistem operasi utama, baik itu Debian, CentOS, Snap, MacOS, OpenBSD, Windows atau lainnya. Kami mencatat bahwa ada juga build untuk Windows yang menyertakan Ruby dan paket dasar. Opsi ini cocok bagi mereka yang ingin menyederhanakan instalasi Ruby mereka. Jika Anda memutuskan untuk menggunakan penginstal, jangan lupa untuk mencentang kotak di tempat yang diperlukan selama instalasi:


Instal Ruby

Hal ini diperlukan agar komputer mengetahui di mana lokasi executable dan dapat mengaitkan semua file berekstensi *.rb dan *.rbw dengan Ruby.

Setelah Anda menginstal Ruby, Anda dapat memeriksa apakah semuanya berjalan baik dengan menjalankan perintah berikut pada baris perintah:

ruby -v

Ini akan mengembalikan baris dengan versi Ruby:

ruby 3.2.2 (2023-03-30 revision e51014f9c0) (x64-mingw-ucrt)

Sekarang putuskan di mana Anda ingin menulis kode. Sebenarnya hal ini tidak terlalu penting. Anda dapat menjalankan file kode dari baris perintah dan bahkan menulis kode di Notepad. Namun, lebih baik menggunakan alat khusus untuk ini yang menyorot sintaks dan memberi tahu Anda di mana letak kesalahannya. Untuk keperluan ini Anda bisa menggunakan Sublime, Visual Code atau yang lainnya.

Menginstal perpustakaan

Ketika bagian ini selesai, Anda dapat mulai menginstal perpustakaan. Dalam tutorial ini kita akan melihat perpustakaan berikut:

  1. pesta HTTP. Pustaka kueri berfitur lengkap yang memungkinkan Anda melakukan kueri GET, POST, PUT, dan DELETE. Meskipun tidak dirancang khusus untuk web scraping, ini dapat berguna untuk mengambil data dari situs web dan API.
  2. Bersih::HTTP. Pustaka lain yang memungkinkan Anda menjalankan dan memproses kueri.
  3. Nokogiri. Ini adalah perpustakaan lengkap untuk parsing dan pemrosesan dokumen XML dan HTML. Itu tidak bisa menjalankan kueri, tapi bagus untuk memproses data keluaran. Keuntungan utamanya adalah kemampuan untuk bekerja dengan pemilih CSS, tetapi tidak dengan XPath.
  4. Mekanisasi. Ini adalah perpustakaan terpopuler kedua yang digunakan untuk web scraping Ruby. Berbeda dengan Nokogiri, ia menawarkan kemampuan untuk meminta data sendiri.
  5. Watir. Ini adalah kerangka pengujian aplikasi web yang juga dapat digunakan untuk web scraping. Ini memungkinkan Anda untuk mengotomatiskan interaksi dengan halaman web dengan cara yang mirip dengan Mekanisasi. Namun, browser tanpa kepala juga bisa digunakan.

Selain yang disebutkan sebelumnya, masih banyak permata Ruby lainnya untuk web scraping, seperti PhantomJS, Capybara atau Kimurai Gemfile. Namun, perpustakaan yang disarankan di atas lebih populer dan terdokumentasi dengan lebih baik, jadi kami akan fokus pada perpustakaan tersebut di artikel ini.

Untuk menginstal paket di Ruby, gunakan Instal permata Memerintah:

gem install httparty
gem install nokogiri
gem install mechanize
gem install watir

Net::HTTP tidak perlu diinstal karena sudah diinstal sebelumnya. Anda dapat menggunakan Ruby Gem untuk memeriksa ini:

Analisis halaman

Sebagai contoh, mari kita ambil situs pengujian dengan buku-buku yang bisa kita cari. Pertama, mari kita buka halamannya dan lihat kode HTMLnya. Untuk membuka kode halaman HTML, buka DevTools (tekan F12 atau klik kanan pada ruang kosong di halaman dan buka Inspect).


Lakukan beberapa penelitian

Semua produk di situs ada di

    -Tag dengan kelas "baris" dan setiap produk di sub-tag

  1. ditempatkan. Mari kita lihat lebih dekat salah satu produknya:


    Lihatlah strukturnya

    Berdasarkan kode HTML tersebut, kita dapat memperoleh data sebagai berikut:

    1. Tautan gambar. Terletak di tag dan merupakan konten dari atribut “href”.
    2. Evaluasi. Ada dua kelas di dalamnya

      -Tag: peringkat bintang dan peringkat buku. Dalam contoh kita, rating buku adalah 3.

    3. Judul. Judul buku sudah masuk -Hari. Namun, itu tidak sepenuhnya ditentukan dalam tag. Judul lengkap ada pada atribut “title”.
    4. Harga. Di sini kita hanya perlu kontennya saja
      -Dapatkan tag dengan kelas “harga_produk”.
    5. Ketersediaan. Di sini Anda harus memperhatikan kelas. Kelas “icon-ok” digunakan untuk buku yang tersedia.

    Sekarang setelah Anda menginstal semua komponen yang diperlukan, saatnya mulai membuat scraper Anda. Dengan Ruby dan alat yang tepat, mengambil data dari situs web menjadi relatif mudah.

    Buat pengikis web

    Buat file *.rb baru, misalnya “scraper.rb” dan buka. Dalam file ini kita akan menulis kode untuk mengikis data menggunakan Ruby. Pertama, mari kita lihat masing-masing perpustakaan yang terinstal satu per satu untuk melihat bagaimana mereka dapat membantu kita mengambil informasi dari situs web atau sumber lain.

    Buat permintaan HTTP dengan HTTParty

    Perpustakaan pertama dalam daftar kami adalah perpustakaan HTTParty. Itu tidak memungkinkan Anda memproses atau menganalisis data, namun memungkinkan Anda menjalankan kueri. Mari kita hubungkan:

    require "httparty" 

    Mari jalankan kueri dan dapatkan kode halaman books.toscrape.com:

    response = HTTParty.get("https://books.toscrape.com/catalogue/page-1.html")

    Untuk melihat hasilnya, Anda dapat menggunakannya menempatkan() Memerintah:

    puts(response)

    Hasilnya, kami mendapatkan kode HTML halaman tersebut:

    D:\scripts\ruby>ruby scraper.rb
    <!DOCTYPE html>
    <!--(if lt IE 7)>      <html lang="en-us" class="no-js lt-ie9 lt-ie8 lt-ie7"> <!(endif)-->
    <!--(if IE 7)>         <html lang="en-us" class="no-js lt-ie9 lt-ie8"> <!(endif)-->
    <!--(if IE 8)>         <html lang="en-us" class="no-js lt-ie9"> <!(endif)-->
    <!--(if gt IE 8)><!--> <html lang="en-us" class="no-js"> <!--<!(endif)-->
        <head>
            <title>
        Semua produk | Buku untuk Dikikis - Kotak Pasir ...
    </title>
    </head>
    </html>

    Sayangnya, banyak situs web yang mencoba menolak akses scraper ke data mereka. Untuk menyamarkan scraper Anda agar tidak mengakses data, ada beberapa metode yang dapat Anda gunakan: menggunakan proxy dan API web scraping; mengatur penundaan acak antar permintaan; Menggunakan browser tanpa kepala. Penting juga untuk menyertakan agen pengguna dalam setiap permintaan yang dikirim. Hal ini meningkatkan kemungkinan scraper Anda terhindar dari pemblokiran.

    response = HTTParty.get("https://books.toscrape.com/catalogue/page-1.html", { 
        headers: { 
            "User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36" 
        }, 
    })

    Ingatlah bahwa lebih baik menggunakan agen pengguna yang sebenarnya.

    Mengikis data dengan HTTParty dan Web Scraping API

    Seperti yang telah disebutkan, perpustakaan HTTParty dirancang hanya untuk mengirim permintaan. Namun, kita dapat menggunakan web scraping API untuk memproses data. Untuk melakukan ini kami memerlukan kunci API, yang akan Anda terima setelah mendaftar dengan Scrape-It.Cloud. Kami juga membutuhkan perpustakaan tambahan:

    gem install json

    Hubungkan perpustakaan ini di file kami:

    require "json"

    Sekarang mari kita buat permintaan ke API. Kami perlu memberikan beberapa informasi yang mengungkapkan apa yang kami cari. Hal ini termasuk menentukan header permintaan (misalnya tipe data apa yang kami inginkan dan kunci API Anda) dan isi (konten sebenarnya dari permintaan kami):

    url = "https://api.scrape-it.cloud/scrape"
    headers = {
      "x-api-key" => "YOUR-API-KEY",
      "Content-Type" => "application/json"
    }
    payload = {
      extract_rules: {
        title: "h3>a @title",
        price: "div.product_price>p.price_color",
        image: "div.image_container>a @href",
        rating: "p.star-rating @class",
        available: "p.availability>i @class"
      },
      wait: 0,
      screenshot: true,
      block_resources: false,
      url: "https://books.toscrape.com/catalogue/page-1.html"
    }.to_json
    

    Kemudian kami menjalankan kueri:

    response = HTTParty.post(url, headers: headers, body: payload)
    parsed_page = JSON.parse(response.body)

    Sekarang kita dapat mereferensikan atribut respons JSON yang dikembalikan kepada kita oleh Scrape-It.Cloud API, yang berisi data yang diperlukan:

    parsed_page = JSON.parse(response.body)
    extracted_data = parsed_page("scrapingResult")("extractedData")

    Sekarang kita sudah memiliki datanya, mari kita simpan dalam file CSV.

    Simpan data dalam format CSV

    Mari kita mulai dengan menginstal perpustakaan CSV:

    gem install csv

    Kaitkan perpustakaan dengan file:

    require "csv"

    Untuk menyimpan data ke file, kita perlu membukanya dengan pengaturan yang benar. Kami menggunakan “w” – jika file belum ada, ini akan membuatkan file untuk kami. Jika ada, konten apa pun yang ada akan ditimpa. Kita juga dapat menentukan karakter mana yang memisahkan masing-masing informasi - kita menggunakan titik koma (;):

    CSV.open("data.csv", "w", col_sep: ";") do |csv|
    …
    end

    Mari kita atur judul kolom:

    csv << ("Title", "Price", "Image", "Rating", "Availability")

    Terakhir, mari kita telusuri semua array yang kita terima baris demi baris dan menulis datanya ke file:

    (extracted_data("title"), extracted_data("price"), extracted_data("image"), extracted_data("rating"), extracted_data("available")).transpose.each do |row|
          csv << row
        end

    Hasilnya, kami mendapatkan tabel berikut:


    Hasil pertama

    Kelihatannya bagus, tapi kita bisa membuatnya lebih baik lagi dengan membersihkan data. Untungnya, hal ini mudah dilakukan dengan fitur bawaan Ruby. Kita bisa memulai dengan simbol pound (£) pada harga, yang muncul sebagai “BJ” saat disimpan ke file:

    extracted_data("price") = extracted_data("price").map { |price| price.gsub("£", "") }

    Di kolom “Rating” kami memiliki dua kelas yang berbeda. Kita hanya membutuhkan yang kedua, jadi kita selesaikan masalah ini menggunakan metode split(). Ini mengambil string kita dan membaginya menjadi array string berdasarkan pola atau karakter tertentu:

    extracted_data("rating") = extracted_data("rating").map { |rating| rating.split(" ").last }

    Sekarang mari kita jalankan query lagi dan lihat tabelnya:


    Bersihkan datanya

    Sekarang hasilnya terlihat lebih baik dan akan lebih mudah untuk diedit di kemudian hari.

    Kode yang dihasilkan:

    require "httparty"
    require "json"
    require "csv"
    
    url = "https://api.scrape-it.cloud/scrape"
    headers = {
      "x-api-key" => "YOUR-API-KEY",
      "Content-Type" => "application/json"
    }
    payload = {
      extract_rules: {
        title: "h3>a @title",
        price: "div.product_price>p.price_color",
        image: "div.image_container>a @href",
        rating: "p.star-rating @class",
        available: "p.availability>i @class"
      },
      wait: 0,
      screenshot: true,
      block_resources: false,
      url: "https://books.toscrape.com/catalogue/page-1.html"
    }.to_json
    
    response = HTTParty.post(url, headers: headers, body: payload)
    parsed_response = JSON.parse(response.body)
    extracted_data = parsed_response("scrapingResult")("extractedData")
    
    # Remove pound symbol (£) from price values
    extracted_data("price") = extracted_data("price").map { |price| price.gsub("£", "") }
    
    # Extract only the second word from the rating values
    extracted_data("rating") = extracted_data("rating").map { |rating| rating.split(" ").last }
    
    CSV.open("data.csv", "w", col_sep: ";") do |csv|
        csv << ("Title", "Price", "Image", "Rating", "Availability")
      
        (extracted_data("title"), extracted_data("price"), extracted_data("image"), extracted_data("rating"), extracted_data("available")).transpose.each do |row|
          csv << row
        end
      end
      
      
      puts "Data saved to data.csv"

    Sekarang kita telah melihat perpustakaan HTTParty, mari kita lihat apa yang akan terlihat jika kita menggunakan Net::HTTP sebagai gantinya. Kita akan dapat memahami apa yang membuat perpustakaan ini unik dan mencari tahu mana yang terbaik untuk kebutuhan scraping kita.

    Buat permintaan menggunakan NET::HTTP

    Pustaka Net::HTTP yang disediakan oleh permata net-http dapat digunakan bersama dengan permata open-uri untuk fungsionalitas tambahan. Net::HTTP menyediakan akses ke protokol HTTP yang mendasarinya, sementara open-uri membuat permintaan data dari server jarak jauh menjadi lebih mudah dan efisien. Bersama-sama, mereka menyediakan cara yang efektif untuk mengambil informasi dari situs web dengan cepat.

    Pertama, mari kita sambungkan perpustakaan:

    require "uri"
    require "net/http"

    Kemudian kita perlu mengurai string URL menjadi objek Uniform Resource Identifier (URI):

    url = URI.parse("https://books.toscrape.com/catalogue/page-1.html")

    Ini membantu memecah URL menjadi beberapa bagian komponennya, memungkinkan akses mudah dan pengeditan berbagai komponen sesuai kebutuhan. Dan akhirnya kita bisa menjalankan query dan menampilkannya ke baris perintah:

    request = Net::HTTP.get_response(url)
    puts request.body

    Ini memungkinkan Anda membuat permintaan “GET” sederhana untuk mengambil data dari web menggunakan perpustakaan Net::HTTP. Ini bisa menjadi cara terbaik untuk mengakses dan mengekstrak data dengan cepat dari situs web mana pun.

    Mengikis data menggunakan Net::HTTP dan Web Scraping API

    Untuk tugas ini kami menggunakan API Scrape-It.Cloud. Pertama kita perlu menentukan titik akhir API untuk mengirim permintaan kita. Kita juga perlu menentukan header dan isi permintaan POST. Pada dasarnya ini berarti kami menyediakan API dengan detail tentang apa yang ingin kami evaluasi. Kita perlu memberikan URL halaman yang ingin kita cari dan memberitahukan konten apa yang ingin kita ekstrak:

    url = URI("https://api.scrape-it.cloud/scrape")
    
    https = Net::HTTP.new(url.host, url.port)
    https.use_ssl = true
    
    request = Net::HTTP::Post.new(url)
    request("x-api-key") = "YOUR-API-KEY"
    request("Content-Type") = "application/json"
    request.body = JSON.dump({
      "extract_rules": {
        "title": "h3>a @title",
        "price": "div.product_price>p.price_color",
        "image": "div.image_container>a @href",
        "rating": "p.star-rating @class",
        "available": "p.availability>i @class"
      },
      "wait": 0,
      "screenshot": true,
      "block_resources": false,
      "url": "https://books.toscrape.com/catalogue/page-1.html"
    })
    

    Kemudian jalankan kueri dan tampilkan data di layar:

    response = https.request(request)
    puts response.body

    Seperti yang bisa kita lihat, kegunaan perpustakaan ini tidak jauh berbeda dengan yang kita bahas sebelumnya. Jadi mari kita gunakan kode yang sama seperti contoh sebelumnya dan simpan datanya dalam format CSV. Untuk menghindari banyak pengulangan, kami menampilkan versi lengkap dari skrip yang sudah selesai:

    require "uri"
    require "json"
    require "net/http"
    require "csv"
    
    url = URI("https://api.scrape-it.cloud/scrape")
    
    https = Net::HTTP.new(url.host, url.port)
    https.use_ssl = true
    
    request = Net::HTTP::Post.new(url)
    request("x-api-key") = "YOUR-API-KEY"
    request("Content-Type") = "application/json"
    request.body = JSON.dump({
      "extract_rules": {
        "title": "h3>a @title",
        "price": "div.product_price>p.price_color",
        "image": "div.image_container>a @href",
        "rating": "p.star-rating @class",
        "available": "p.availability>i @class"
      },
      "wait": 0,
      "screenshot": true,
      "block_resources": false,
      "url": "https://books.toscrape.com/catalogue/page-1.html"
    })
    
    response = https.request(request)
    
    parsed_response = JSON.parse(response.body)
    extracted_data = parsed_response("scrapingResult")("extractedData")
    extracted_data("price") = extracted_data("price").map { |price| price.gsub("£", "") }
    extracted_data("rating") = extracted_data("rating").map { |rating| rating.split(" ").last }
    
    CSV.open("data.csv", "w", col_sep: ";") do |csv|
      csv << ("Title", "Price", "Image", "Rating", "Availability")
    
      (extracted_data("title"), extracted_data("price"), extracted_data("image"), extracted_data("rating"), extracted_data("available")).transpose.each do |row|
        csv << row
      end
    end
    
    puts "Data saved to data.csv"

    Sekarang kita telah melihat pustaka kueri, mari beralih menjelajahi pustaka yang menyediakan kemampuan pemrosesan data. Pustaka ini memungkinkan kami mengubah dan memanipulasi data yang kami kumpulkan dengan cara yang bermakna.

    Analisis data menggunakan Nokogiri

    Nokogiri adalah perpustakaan yang sangat berguna untuk memproses dan mengurai data. Mudah digunakan dan sangat populer di kalangan pengembang Ruby. Ini memberikan cara efektif untuk bekerja dengan dokumen HTML dan XML dan membuat pengikisan data menjadi cepat dan mudah.

    Sayangnya, Nokogiri bukanlah perpustakaan scraping yang berdiri sendiri dan tidak memiliki kemampuan untuk mengirim permintaan. Selain itu, ini bagus untuk mengambil data dari halaman statis, tetapi Anda tidak dapat menggunakannya untuk menanyakan dan memproses data dari halaman dinamis. Pada contoh sebelumnya, kami memecahkan masalah ini menggunakan web scraping API. Dengan Nokogiri, semua masalah ini harus diselesaikan sendiri oleh pengembang.

    Namun, jika Anda hanya perlu mengekstrak data dari halaman statis, tidak perlu melakukan tindakan apa pun pada halaman tersebut (misalnya, melakukan otorisasi) dan memerlukan perpustakaan sederhana, maka Nokogiri adalah yang Anda butuhkan.

    Untuk menggunakannya kita memerlukan perpustakaan kueri. Di sini kami menggunakan HTTParty, tetapi Anda dapat menggunakan perpustakaan apa pun yang sesuai dengan kebutuhan Anda. Pertama, mari hubungkan kedua perpustakaan dan dapatkan semua kode halaman kita:

    require 'httparty'
    require 'nokogiri'
    headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
    }
    url = https://books.toscrape.com/catalogue/page-1.html"
    response = HTTParty.get(url, headers: headers)

    Sekarang berikan kode yang Anda terima ke objek Nokogiri. Kemudian struktur halaman dianalisis dan Anda dapat mengakses berbagai elemen di halaman ini dengan lebih mudah:

    doc = Nokogiri::HTML(response.body)

    Sekarang kita bisa mendapatkan data yang diperlukan dari halaman menggunakan pemilih CSS:

    titles = doc.css('h3 > a').map { |element| element('title') }
    prices = doc.css('div.product_price > p.price_color').map { |element| element.text.gsub("£", "") }
    images = doc.css('div.image_container > a').map { |element| element('href') }
    ratings = doc.css('p.star-rating').map { |element| element('class').split(' ').last }
    availabilities = doc.css('p.availability > i').map { |element| element('class').split('-').last }

    Kami telah menyempurnakan informasi yang kami miliki dengan menggunakan taktik untuk mengatasi masalah yang kami temui sebelumnya. Untuk memulai, kita memiliki fungsi yang disebut { |elemen| menggunakan elemen('Attributes') }, yang menggantikan "atribut" dengan nama atribut yang isinya ingin Anda akses. Hal ini memungkinkan kita untuk mendapatkan konten atribut setiap elemen, bukan teks.

    Kami kemudian menggunakan perintah gsub(“£”, “”) untuk membersihkan setiap elemen dalam array harga. Kita perlu menghilangkan tanda nomor tersebut karena tidak muncul dengan benar saat menyimpan data ke file. Terakhir, kami menggunakan split(“”) untuk memisahkan susunan peringkat dan ketersediaan menjadi dua bagian. Kami kemudian menggunakan .last untuk setiap array, hanya menyisakan bagian kedua.

    Seperti yang bisa kita lihat, penggunaan Nokogiri cukup sederhana dan tidak akan menimbulkan kesulitan bahkan bagi pemula sekalipun.

    Menggaruk beberapa halaman

    Sekarang setelah kita mengetahui cara mengekstrak data dari satu halaman, mari gunakan data tersebut untuk mengumpulkan informasi dari setiap halaman situs web. Terakhir, pembuatan scraper biasanya tidak hanya untuk satu situs; Mereka sering digunakan untuk mencari seluruh situs web atau toko online.

    Sayangnya Nokogiri tidak mengizinkan kita untuk berpindah ke halaman berikutnya dengan menekan tombol tersebut. Namun, kami dapat mengidentifikasi pola pembuatan tautan di situs dan menyarankan seperti apa tampilan halaman berikutnya.

    Perhatikan baik-baik tautan halaman:

    https://books.toscrape.com/catalogue/page-1.html
    https://books.toscrape.com/catalogue/page-2.html
    ...
    https://books.toscrape.com/catalogue/page-50.html

    Seperti yang bisa kita lihat, pada halaman contoh ini hanya nomor halamannya saja yang berubah. Totalnya ada 50 halaman. Mari tambahkan bagian awal yang tidak diubah ke variabel base_url:

    base_url="https://books.toscrape.com/catalogue/page-"

    Selain itu, kami memiliki agen pengguna yang konstan untuk semua permintaan:

    headers = {
     'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
    }

    Terakhir, kita perlu mengatur jumlah halaman dan variabel dimana data semua halaman akan disimpan:

    total_pages = 50
    data = ()

    Sebenarnya, kita bisa membawa scraper kita ke tingkat berikutnya dan tidak perlu menentukan secara manual berapa banyak halaman yang ada. Sebagai gantinya, kita dapat menggunakan kode yang mendapatkan jumlah halaman dari halaman itu sendiri atau mengulang hingga terjadi kesalahan 404 Not Found. Namun, dalam kasus ini, kerumitan kode seperti itu tidak diperlukan, karena tautan memiliki struktur yang jelas dan mudah diprediksi.

    Sekarang mari kita buat loop untuk menelusuri setiap halaman dan menghasilkan link yang sesuai. Jumlah iterasi dalam perulangan sesuai dengan nomor halaman. Misalnya, pada lintasan pertama melalui perulangan kita membuat tautan untuk halaman pertama; pada iterasi kedua – halaman kedua; Dan seterusnya:

    (1..total_pages).each do |page|
        url = "#{base_url}#{page}.html"
    
        response = HTTParty.get(url, headers: headers)
        doc = Nokogiri::HTML(response.body)
    end

    Pemilih CSS dan variabel yang dapat diambil tetap tidak berubah. Jadi mari kita mulai memasukkan data ke dalam hash:

    page_data = titles.zip(prices, images, ratings, availabilities).map do |title, price, image, rating, availability|
        { title: title, price: price, image: image, rating: rating, availability: availability }
        end

    Terakhir, kami menambahkan data di bagian akhir Data Variabel yang kita buat di awal:

    data.concat(page_data)

    Disarankan juga untuk menambahkan penundaan acak untuk meningkatkan kemungkinan melewati blok:

    sleep(rand(1..3))

    Setelah menjalankan siklus, simpan data ke file CSV:

    CSV.open('book_data.csv', 'w', col_sep: ";") do |csv|
      csv << data.first.keys # Write the headers
      data.each { |hash| csv << hash.values } # Write the data rows
    end

    Hasilnya, skrip kami melewati semua halaman, mengumpulkan data, dan memasukkannya ke dalam file CSV:


    Kikis produk apa pun

    Kode lengkap:

    require 'httparty'
    require 'nokogiri'
    require 'csv'
    
    base_url="https://books.toscrape.com/catalogue/page-"
    headers = {
      'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
    }
    total_pages = 50
    data = ()
    
    (1..total_pages).each do |page|
        url = "#{base_url}#{page}.html"
    
        response = HTTParty.get(url, headers: headers)
        doc = Nokogiri::HTML(response.body)
    
        # Extracting data
        titles = doc.css('h3 > a').map { |element| element('title') }
        prices = doc.css('div.product_price > p.price_color').map { |element| element.text.gsub("£", "") }
        images = doc.css('div.image_container > a').map { |element| element('href') }
        ratings = doc.css('p.star-rating').map { |element| element('class').split(' ').last }
        availabilities = doc.css('p.availability > i').map { |element| element('class').split('-').last }
    
        # Combine the extracted data into an array of hashes
        page_data = titles.zip(prices, images, ratings, availabilities).map do |title, price, image, rating, availability|
        { title: title, price: price, image: image, rating: rating, availability: availability }
        end
        data.concat(page_data)
        sleep(rand(1..3))
    end
    
    # Save the data to a CSV file
    CSV.open('book_data.csv', 'w', col_sep: ";") do |csv|
      csv << data.first.keys # Write the headers
      data.each { |hash| csv << hash.values } # Write the data rows
    end
    
    puts 'Data saved to book_data.csv'

    Seperti yang bisa kita lihat, bahkan kemampuan perpustakaan Nokogiri cukup untuk menggores situs web.

    Pengikisan web dengan Mekanisasi

    Mechanize adalah perpustakaan lengkap untuk web scraping. Ini berarti Anda tidak memerlukan perpustakaan tambahan apa pun - semua alat yang diperlukan sudah disertakan. Anda dapat menggunakan Mechanize untuk mengirim kueri dan memproses hasilnya.

    Untuk menggunakan perpustakaan Mechanize, kami menghubungkannya di file kami:

    require 'mechanize'

    Kita juga bisa menggunakan fungsi bawaan perpustakaan untuk menjalankan permintaan:

    agent = Mechanize.new
    page = agent.get('https://books.toscrape.com/catalogue/page-1.html')

    Menggunakan pemilih CSS yang sama seperti sebelumnya, Mechanize memungkinkan Anda mengakses dan mengekstrak data:

    titles = page.css('h3 > a').map { |element| element('title') }
    prices = page.css('div.product_price > p.price_color').map { |element| element.text.gsub("£", "") }
    images = page.css('div.image_container > a').map { |element| element('href') }
    ratings = page.css('p.star-rating').map { |element| element('class').split(' ').last }
    availabilities = page.css('p.availability > i').map { |element| element('class').split('-').last }

    Kalau tidak, menggunakan perpustakaan ini sama dengan menggunakan Nokogiri.

    Ambil kategori dengan Mekanisasi

    Katakanlah kita ingin mengumpulkan data dari berbagai kategori. Kita akan mulai dengan menelusuri setiap kategori dan kemudian beralih ke halaman individual dalam kategori tersebut. Untuk setiap produk, kami menyimpannya dalam tabel beserta nama kategorinya.

    Pertama, buka halaman beranda dan dapatkan nama dan tautan semua kategori:

    base_url="https://books.toscrape.com"
    category_links = ()
    category_names = ()
    product_data = ()
    agent = Mechanize.new
    agent.user_agent_alias="Mac Safari" # Set the User-Agent header
    page = agent.get(base_url)
    page.css('div.side_categories > ul > li > ul > li > a').each do |element|
      category_links << element('href')
      category_names << element.text.gsub(" ", "").strip
    end

    Di sini kami menggunakan gsub() untuk menghapus spasi ekstra dan strip untuk menghapus baris kosong. Untuk mengulangi semua kategori, kami menggunakan loop:

    category_links.each_with_index do |category_link, index|
    …
    end

    Pemilih CSS akan tetap sama, jadi kami tidak akan menduplikasinya, namun hashnya akan sedikit berubah sehingga kami dapat mempertahankan nama kategori:

    product_data << { category: category_names(index), title: title, price: price, image: image, rating: rating, availability: availability }

    Dengan menjalankan skrip kami, kami mendapatkan tabel data:


    Mengikis kategori

    Kode lengkap:

    require 'mechanize'
    require 'csv'
    
    base_url="https://books.toscrape.com"
    category_links = ()
    category_names = ()
    product_data = ()
    
    agent = Mechanize.new
    agent.user_agent_alias="Mac Safari" # Set the User-Agent header
    
    # Get category links and names
    page = agent.get(base_url)
    page.css('div.side_categories > ul > li > ul > li > a').each do |element|
      category_links << element('href')
      category_names << element.text.gsub(" ", "").strip
    end
    
    # Iterate over each category
    category_links.each_with_index do |category_link, index|
      category_url = "#{base_url}/#{category_link}"
      page = agent.get(category_url)
    
      # Scrape product data
      page.css('article.product_pod').each do |product|
        title = product.css('h3 > a').first('title')
        price = product.css('div.product_price > p.price_color').text.gsub("£", "")
        image = product.css('div.image_container > a > img').first('src')
        rating = product.css('p.star-rating').first('class').split(' ').last
        availability = product.css('p.availability > i').first('class').split('-').last
    
        product_data << { category: category_names(index), title: title, price: price, image: image, rating: rating, availability: availability }
      end
    
      sleep(rand(1..3)) # Add a random delay between requests
    end
    
    # Save the data to a CSV file
    CSV.open('book_data.csv', 'w', col_sep: ";") do |csv|
      csv << product_data.first.keys # Write the headers
      product_data.each { |hash| csv << hash.values } # Write the data rows
    end
    
    puts 'Data saved to book_data.csv'

    Singkatnya, tidak terlalu sulit untuk mengekstrak detail produk seperti nama kategori dan menyimpannya ke file CSV jika Anda menggunakan perpustakaan Mechanize.

    Mengikis data dinamis dengan Watir menggunakan browser tanpa kepala

    Kerangka kerja Watir berbeda dari perpustakaan scraping lainnya karena dapat digunakan dengan browser tanpa kepala. Ini berarti kode kami bertindak seperti pengguna sebenarnya dan memiliki peluang lebih besar untuk tidak diblokir. Ini berfungsi dengan memungkinkan kita menampilkan atau menyembunyikan jendela browser saat mengakses semua fungsinya seperti: B. mengklik link dan mengisi formulir.

    Untuk memulai kita perlu menginstal driver web. Ini adalah perangkat lunak yang membantu kita berinteraksi dengan Internet untuk mengekstrak data.

    gem install webdrivers

    Untuk tutorial ini kami akan menggunakan driver web Chrome, namun Anda juga dapat menggunakan driver web lain yang didukung oleh Watir seperti Firefox atau Safari. Jadi mari kita sambungkan perpustakaan yang diperlukan dan buat objek browser:

    require 'watir'
    require 'webdrivers'
    browser = Watir::Browser.new(:chrome)

    Untuk hasil yang sama Anda juga dapat menggunakan Selenium:

    browser = Selenium::WebDriver::Chrome::Options.new

    Perintah goto() digunakan untuk menavigasi ke halaman lain. Ini dapat digunakan untuk berpindah antar halaman dengan cepat sambil mengambil data dari berbagai sumber:

    browser.goto(' https://books.toscrape.com/index.html')

    Mengikis dengan Watir memiliki satu keuntungan besar: Anda tidak perlu menambahkan parameter tambahan ke kueri. Karena skrip membuat jendela browser nyata dan menangani semua transisi antar halaman, sehingga sudah berisi semua informasi yang diperlukan.

    Buka halaman berikutnya dengan Watir

    Mari tingkatkan kode kita sebelumnya. Katakanlah kita masih ingin mengumpulkan semua artikel dari setiap kategori, namun kali ini kita akan menelusuri halaman-halaman kategori tersebut hingga tidak ada lagi tombol "Berikutnya".

    Lihat tombol Berikutnya:


    Dapatkan halaman berikutnya

    Ini menyimpan link ke halaman berikutnya dan memiliki kelas "berikutnya". Artinya kita dapat membuat loop dengan ketentuan sebagai berikut:

    base_url="https://books.toscrape.com"
    
    loop do
    	…
    next_link = browser.li(class: 'next').a
    break unless next_link.exists?
    browser.goto("#{base_url}/#{next_link.href}")
    end

    Dengan menyematkan loop ke dalam loop kategori yang ada, kita dapat melakukan iterasi melalui halaman mana pun di semua kategori dengan cepat dan efisien. Hal ini memungkinkan kami menghindari tugas berat dalam menavigasi setiap halaman setiap kategori secara manual.

    Akses data dengan Watir berbeda dari perpustakaan yang dibahas sebelumnya, tetapi membuatnya lebih mudah untuk berinteraksi dengan elemen dalam struktur Document Object Model (DOM). Misalnya, dapatkan data yang sama seperti sebelumnya:

    product_data =()
    browser.articles(class: 'product_pod').each do |product|
          title = product.h3.a.title
          price = product.div(class: 'product_price').p(class: 'price_color').text.gsub('£', '')
          image = product.div(class: 'image_container').a.href
          rating = product.p(class: 'star-rating').class_name.split(' ').last
          availability = product.p(class: 'availability').i.class_name.split('-').last
    
          product_data << { category: category_names(index), title: title, price: price, image: image, rating: rating, availability: availability }
    end

    Di akhir skrip, pastikan untuk menyertakan perintah untuk menutup browser:

    browser.quit

    Kode lengkap:

    require 'watir'
    require 'webdrivers'
    require 'csv'
    
    base_url="https://books.toscrape.com"
    category_links = ()
    category_names = ()
    product_data = ()
    
    # Launch a browser (in this case, Chrome)
    browser = Watir::Browser.new(:chrome)
    
    # Navigate to the main page
    browser.goto(base_url)
    
    # Get category links and names
    browser.div(class: 'side_categories').ul(class: 'nav').li(class: 'active').ul.lis.each do |li|
      link = li.a.href
      name = li.a.text.gsub(' ', '')
      category_links << link
      category_names << name
    end
    
    # Iterate over each category
    category_links.each_with_index do |category_link, index|
      category_url = "#{base_url}/#{category_link}"
      browser.goto(category_url)
    
      loop do
        # Scrape product data from the current page
        browser.articles(class: 'product_pod').each do |product|
          title = product.h3.a.title
          price = product.div(class: 'product_price').p(class: 'price_color').text.gsub('£', '')
          image = product.div(class: 'image_container').a.href
          rating = product.p(class: 'star-rating').class_name.split(' ').last
          availability = product.p(class: 'availability').i.class_name.split('-').last
    
          product_data << { category: category_names(index), title: title, price: price, image: image, rating: rating, availability: availability }
        end
    
        # Check if there's a "Next" link
        next_link = browser.link(class: 'next')
        break unless next_link.exists?
    
        # Navigate to the next page
        browser.goto(next_link.href)
        sleep(rand(1..3)) # Add a random delay between requests
      end 
    end
    
    # Close the browser
    browser.quit
    
    # Save the data to a CSV file
    CSV.open('book_data.csv', 'w', col_sep: ';') do |csv|
      csv << product_data.first.keys # Write the headers
      product_data.each { |hash| csv << hash.values } # Write the data rows
    end
    
    puts 'Data saved to book_data.csv'

    Setelah menggunakan Watir dalam praktiknya, kami dapat mengatakan bahwa ini adalah perpustakaan Ruby yang kuat yang menyediakan cara mudah untuk mengotomatisasi interaksi browser.

    Meskipun ada alternatif web scraping lain di Ruby, seperti Nokogiri dan Mechanize, Watir menawarkan solusi yang lebih komprehensif untuk mengotomatiskan interaksi browser dan memberikan tingkat kontrol yang lebih tinggi atas tugas web scraping.

    Kesimpulan dan temuan

    Ruby menjadikan web scraping pilihan yang bagus bagi pengembang yang perlu mengumpulkan data dalam jumlah besar dengan cepat dan akurat. Pada artikel ini, kita telah membahas berbagai cara untuk mengikis data menggunakan Ruby. Kami memulai dengan opsi paling sederhana seperti pustaka kueri dan API pengikisan web sebelum beralih ke solusi yang lebih kompleks seperti menggunakan Watir dan driver web.

    Saat memutuskan pustaka atau teknik mana yang akan digunakan, ingatlah untuk mempertimbangkan faktor-faktor seperti kompleksitas situs web target, kebutuhan rendering JavaScript, persyaratan otomatisasi browser, dan pemahaman Anda terhadap pustaka tersebut.

    Jika Anda baru memulai dengan Ruby, menggunakan API untuk web scraping adalah pilihan yang baik. Dengan cara ini Anda tidak perlu khawatir tentang hal-hal rumit seperti rendering JavaScript, penyelesaian CAPTCHA, penggunaan proxy, atau menghindari pemblokiran. Jika hal ini tidak terjadi dan Anda memerlukan sesuatu yang sederhana, Nokogiri atau Mechanize ideal untuk membuang sumber daya statis. Namun, jika Anda memerlukan fitur-fitur canggih - seperti kemampuan untuk meniru perilaku pengguna nyata pada suatu halaman - maka Watir dan Webdriver (atau serupa, misalnya Ruby on Rails) adalah pilihan terbaik.

Pos terkait

Tinggalkan Komentar