Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby
Code

Membangun Scraper Web Pertama Anda, Bagian 3

by
Length:LongLanguages:

Indonesian (Bahasa Indonesia) translation by Ilham Saputra (you can also view the original English article)

Selamat datang kembali ke seri ini untuk membuat scraper web. Dalam tutorial ini, saya akan melihat contoh dari data yang diambil dari situs podcast saya sendiri. Saya akan membahas secara terperinci bagaimana saya mengekstraksi data, bagaimana metode penolong dan utilitas menyelesaikan pekerjaan mereka, dan bagaimana semua kepingan puzzle bersatu.

Topik

  • Scraping Podcast Saya
  • Membongkar
  • Scraper
  • Metode Helper
  • Menulis Posting

Scraping Podcast Saya

Mari letakkan apa yang telah kita pelajari sejauh ini dalam praktik. Karena berbagai alasan, desain ulang untuk podcast saya Antara | Layar sudah lama terlambat. Ada masalah yang membuat saya berteriak ketika saya bangun di pagi hari. Jadi saya memutuskan untuk membuat situs statis baru, yang dibangun bersama dengan Middleman dan dihosting dengan Halaman GitHub.

Saya menginvestasikan banyak waktu pada desain baru setelah saya mengubah blog seorang Middleman sesuai dengan kebutuhan saya. Yang tersisa adalah mengimpor konten dari aplikasi Sinatra yang didukung oleh database, jadi saya perlu mengikis konten yang ada dan mentransfernya ke situs statis baru saya.

Melakukan ini dengan tangan dalam mode goblok tidak ada di meja—bahkan bukan pertanyaan—karena aku bisa mengandalkan teman-temanku Nokogiri dan Mechanize untuk melakukan pekerjaan itu untukku. Apa yang ada di depan Anda adalah pekerjaan pengikisan yang cukup kecil yang tidak terlalu rumit tetapi menawarkan beberapa tikungan menarik yang harus mendidik bagi para pemula web yang mengorek di luar sana.

Di bawah ini adalah dua screenshot dari podcast saya.

Cuplikan Layar Podcast Lama

A screenshot of an old podcast

Cuplikan Layar Podcast Baru

A screenshot of a new podcast

Mari kita memecah apa yang ingin kita capai. Kami ingin mengekstrak data berikut dari 139 episode yang tersebar di 21 situs indeks paginasi:

  • judul
  • orang yang diwawancara
  • subheader dengan daftar topik
  • nomor trek SoundCloud untuk setiap episode
  • tanggal
  • nomor episode
  • teks dari catatan acara
  • tautan dari catatan acara

Kami melakukan iterasi melalui penomoran halaman dan biarkan Mekanize mengklik setiap tautan untuk sebuah episode. Pada halaman detail berikut, kita akan menemukan semua informasi dari atas yang kita butuhkan. Dengan menggunakan data yang tergores, kami ingin mengisi materi depan dan "body" dari file penurunan harga untuk setiap episode.

Di bawah ini Anda dapat melihat pratinjau tentang bagaimana kami akan menyusun file penurunan harga baru dengan konten yang kami ekstrak. Saya pikir ini akan memberi Anda ide yang baik tentang ruang lingkup di depan kita. Ini merupakan langkah terakhir dalam skrip kecil kami. Jangan khawatir, kami akan membahasnya lebih detail.

def compose_markdown

Saya juga ingin menambahkan beberapa trik yang tidak bisa dimainkan oleh situs lama. Memiliki sistem penandaan yang menyeluruh dan komprehensif adalah sangat penting bagi saya. Saya ingin pendengar memiliki alat penemuan yang mendalam. Oleh karena itu, saya membutuhkan tag untuk setiap orang yang diwawancara dan membagi subheader ke dalam tag juga. Karena saya menghasilkan 139 episode di musim pertama saja, saya harus menyiapkan situs untuk waktu ketika jumlah konten menjadi lebih sulit untuk disisir. Sistem penandaan yang mendalam dengan rekomendasi yang ditempatkan cerdas adalah cara untuk pergi. Ini memungkinkan saya untuk menjaga situs ringan dan cepat.

Mari kita lihat kode lengkap untuk menggores konten situs saya. Lihatlah ke sekeliling dan coba cari gambaran besar tentang apa yang sedang terjadi. Karena saya mengharapkan Anda berada di sisi pemula hal-hal, saya menjauhkan diri dari terlalu banyak mengaburkan dan keliru pada sisi kejelasan. Saya melakukan beberapa refactorings yang ditargetkan pada kode bantuan kejelasan, tapi saya juga meninggalkan sedikit daging di tulang untuk Anda bermain dengan ketika Anda selesai dengan artikel ini. Setelah semua, kualitas pembelajaran terjadi ketika Anda melampaui membaca dan main-main dengan beberapa kode pada Anda sendiri.

Sepanjang perjalanan, saya sangat mendorong Anda untuk mulai berpikir tentang bagaimana Anda dapat memperbaiki kode di depan Anda. Ini akan menjadi tugas akhir Anda di bagian akhir artikel ini. Sedikit petunjuk dari saya: memecah metode besar menjadi metode yang lebih kecil selalu menjadi titik awal yang baik. Setelah Anda memahami bagaimana kode bekerja, Anda harus memiliki waktu yang menyenangkan dalam mengasah refactoring tersebut.

Saya sudah mulai dengan mengekstraksi banyak metode menjadi pembantu yang kecil dan terfokus. Anda harus dengan mudah dapat menerapkan apa yang telah Anda pelajari dari artikel saya sebelumnya tentang code smells dan refactorings mereka. Jika ini masih di atas kepala Anda sekarang, jangan khawatir—kami semua sudah ada di sana. Teruslah melakukannya, dan pada beberapa titik hal-hal akan mulai mengklik lebih cepat.

Kode Lengkap

Mengapa kita tidak require "Nokogiri"? Mekanize memberi kita semua kebutuhan pengikisan kita. Seperti yang telah kita bahas pada artikel sebelumnya, Mechanize dibangun di atas Nokogiri dan memungkinkan kita untuk mengekstrak konten juga. Itu, bagaimanapun, penting untuk menutupi permata itu di artikel pertama karena kami perlu membangun di atasnya.

Membongkar

Hal pertama yang pertama. Sebelum kami melompat ke kode kami di sini, saya pikir perlu untuk menunjukkan kepada Anda bagaimana Anda dapat secara efisien memeriksa apakah kode Anda berfungsi seperti yang diharapkan setiap langkah. Seperti yang Anda perhatikan, saya telah menambahkan alat lain ke dalam campuran. Di antaranya, Pry sangat berguna untuk debugging.

Jika Anda menempatkan Pry.start(binding) di mana saja dalam kode Anda, Anda dapat memeriksa aplikasi Anda tepat pada saat itu. Anda dapat mengorek objek pada titik-titik tertentu dalam aplikasi. Ini sangat membantu untuk mengambil aplikasi Anda selangkah demi selangkah tanpa tersandung kaki Anda sendiri. Misalnya, mari letakkan tepat setelah fungsi write_page dan periksa apakah link adalah yang kita harapkan.

Membongkar

Jika Anda menjalankan skripnya, kita akan mendapatkan sesuatu seperti ini.

Output

Saat kami meminta objek link, kami dapat memeriksa apakah kami berada di jalur yang benar sebelum kami melanjutkan ke detail penerapan lainnya.

Terminal

Terlihat seperti apa yang kita butuhkan. Hebat, kita bisa melanjutkan. Melakukan langkah demi langkah melalui seluruh aplikasi ini merupakan praktik penting untuk memastikan bahwa Anda tidak tersesat dan Anda benar-benar memahami cara kerjanya. Saya tidak akan membahas Pry di sini secara lebih terperinci karena akan membutuhkan setidaknya artikel lengkap untuk melakukannya. Saya hanya dapat merekomendasikan menggunakannya sebagai alternatif untuk shell IRB standar. Kembali ke tugas utama kita.

Scraper

Sekarang setelah Anda memiliki kesempatan untuk membiasakan diri dengan potongan-potongan teka-teki di tempat, saya sarankan kita membahas satu per satu dan mengklarifikasi beberapa poin menarik di sana-sini. Mari mulai dengan potongan pusat.

podcast_scraper.rb

Apa yang terjadi dalam metode scrape? Pertama-tama, saya mengulang setiap halaman indeks di podcast lama. Saya menggunakan URL lama dari aplikasi Heroku karena situs baru sudah online di betweenscreens.fm. Saya memiliki 20 halaman episode yang perlu saya lewati.

Saya membatasi pengulangan melalui variabel link_range, yang saya perbarui dengan setiap loop. Akan melalui pagination itu sesederhana menggunakan variabel ini di URL setiap halaman. Sederhana dan efektif.

def scrape

Kemudian, setiap kali saya mendapat halaman baru dengan delapan episode lain untuk mengikis, saya menggunakan page.links untuk mengidentifikasi tautan yang ingin kami klik dan ikuti ke halaman detail untuk setiap episode. Saya memutuskan untuk menggunakan berbagai tautan (links[2..8]) karena konsisten di setiap halaman. Itu juga cara termudah untuk menargetkan tautan yang saya perlukan dari setiap halaman indeks. Tidak perlu meraba-raba dengan pemilih CSS di sini.

Kami kemudian memberi makan tautan itu untuk halaman detail ke metode write_page. Di sinilah sebagian besar pekerjaan dilakukan. Kami mengambil tautan itu, mengekliknya, dan mengikutinya ke laman detail tempat kami dapat mulai mengekstrak datanya. Di halaman itu kami menemukan semua informasi yang saya perlukan untuk menyusun episode penurunan harga baru untuk situs baru.

def write_page

def extract_data

Seperti yang Anda lihat di atas, kami mengambil detail_page dan menerapkan banyak metode ekstraksi di atasnya. Kami mengekstrak orang yang interviewee, title, sc_id, text, episode_title, dan episode_number. Saya mem-refactor sekelompok metode helper terfokus yang bertanggung jawab atas tanggung jawab ekstraksi ini. Mari kita lihat cepat mereka:

Metode Helper

Metode Extraction

Saya mengekstrak para penolong ini karena itu memungkinkan saya untuk memiliki metode yang lebih kecil secara keseluruhan. Mengenkapsulasi perilaku mereka juga penting. Kode juga dibaca lebih baik. Sebagian besar dari mereka mengambil detail_page sebagai argumen dan mengekstrak beberapa data spesifik yang kami perlukan untuk posting Middleman kami.

Kami mencari halaman untuk pemilih tertentu dan mendapatkan teks tanpa ruang putih yang tidak perlu.

Kami mengambil judul dan menghapus ? dan # karena ini tidak bermain bagus dengan materi depan di postingan untuk episode kami. Lebih lanjut tentang materi depan di bawah ini.

Di sini kami perlu bekerja sedikit lebih keras untuk mengekstrak id SoundCloud untuk trek yang kami hosting. Pertama kita perlu Mekanize iframes dengan href dari soundcloud.com dan menjadikannya string untuk pemindaian...

Kemudian cocokkan ekspresi reguler untuk digit-digitnya dari id trek—soundcloud_id "221003494" kami.

Mengekstrak menunjukkan catatan lagi cukup mudah. Kita hanya perlu mencari catatan menunjukkan paragraf di halaman detail. Tidak ada kejutan di sini.

Sama berlaku untuk subjudul, kecuali bahwa itu hanya persiapan untuk bersih ekstrak nomor episode dari itu.

Di sini kita membutuhkan ronde lain dari ekspresi reguler. Mari kita lihat sebelum dan sesudah kami menerapkan regex.

episode_subtitle

number

Satu langkah lagi sampai kita memiliki nomor yang bersih.

Kami mengambil nomor itu dengan hash # dan menghapusnya. Voilà, kami memiliki nomor episode 139 pertama kami yang diekstraksi juga. Saya menyarankan agar kita melihat metode utilitas lain juga sebelum kita menyatukannya.

Metode Utility

Setelah semua bisnis ekstraksi itu, kami memiliki beberapa pembersihan yang harus dilakukan. Kita sudah bisa mulai menyiapkan data untuk menyusun penurunan harga. Sebagai contoh, saya mengiris episode_subtitle lagi untuk mendapatkan tanggal yang bersih dan membangun tags dengan metode build_tags.

def clean_date

Kami menjalankan regex lain yang mencari tanggal seperti ini: " Aug 26, 2015". Seperti yang Anda lihat, ini belum sangat membantu. Dari string_date yang kita dapatkan dari subtitle, kita perlu membuat objek Date yang nyata. Kalau tidak, akan sia-sia untuk membuat posting Middleman.

string_date

Oleh karena itu kami mengambil string itu dan melakukan Date.parse. Hasilnya terlihat jauh lebih menjanjikan.

Tanggal

def build_tags

Ini mengambil title dan interviewee kami telah membangun di dalam metode extract_data dan menghapus semua karakter pipa dan sampah. Kami mengganti karakter pipa dengan koma, @, ?, #, dan & dengan string kosong, dan akhirnya menjaga singkatan with.

def strip_pipes

Pada akhirnya kami memasukkan nama yang diwawancarai dalam daftar tag juga, dan memisahkan setiap tag dengan koma.

Before

After

Setiap tag ini akan menjadi tautan ke koleksi pos untuk topik tersebut. Semua ini terjadi di dalam metode extract_data. Mari kita telah melihat di mana kita berada:

def extract_data

Semua yang tersisa untuk dilakukan di sini adalah mengembalikan opsi hash dengan data yang kami ekstrak. Kita dapat memberi makan hash ini ke dalam metode compose_markdown, yang membuat data kami siap untuk ditulis sebagai file yang saya perlukan untuk situs baru saya.

Menulis Posting

def compose_markdown

Untuk mempublikasikan episode podcast di situs Middleman saya, saya memilih untuk menggunakan kembali sistem blognya. Alih-alih membuat tulisan blog "pure", saya membuat catatan acara untuk episode saya yang menampilkan episode yang dihosting SoundCloud melalui iframes. Di situs indeks, saya hanya menampilkan iframe itu plus judul dan lainnya.

Format yang saya butuhkan untuk bekerja ini terdiri dari sesuatu yang disebut materi depan. Ini pada dasarnya adalah toko kunci/nilai untuk situs statis saya. Ini menggantikan kebutuhan database saya dari situs Sinatra lama saya.

Data seperti nama yang diwawancarai, tanggal, ID trek SoundCloud, nomor episode, dan seterusnya masuk di antara tiga tanda garis (---) di atas file episode kami. Di bawah ini muncul konten untuk setiap episode—hal-hal seperti pertanyaan, tautan, hal sponsor, dll.

Front Matter

Dalam metode compose_markdown, saya menggunakan HEREDOC untuk menyusun file dengan materi depan untuk setiap episode yang kami lewati. Dari opsi hash kami memberi makan metode ini, kami mengekstrak semua data yang kami kumpulkan dalam metode helper extract_data.

def compose_markdown

Ini adalah cetak biru untuk episode podcast baru di sana. Ini adalah tujuan kami. Mungkin Anda bertanya-tanya tentang sintaks khusus ini: #{options[:interviewee]}. Saya melakukan interpolasi seperti biasa dengan string, tetapi karena saya sudah berada di dalam <<-HEREDOC, saya dapat meninggalkan tanda kutip ganda.

Hanya untuk mengorientasikan diri, kita masih dalam pengulangan, di dalam fungsi write_page untuk setiap tautan yang diklik ke halaman detail dengan catatan acara dari episode tunggal. Apa yang terjadi selanjutnya adalah mempersiapkan untuk menulis cetak biru ini ke sistem file. Dengan kata lain, kami membuat episode sebenarnya dengan memberikan nama file dan markdown_text yang dibuat.

Untuk langkah terakhir, kita hanya perlu menyiapkan bahan-bahan berikut: tanggal, nama orang yang diwawancara, dan nomor episode. Selain itu, markdown_text tentu saja, yang baru kami dapatkan dari compose_markdown.

def write_page

Maka kita hanya perlu mengambil file_name dan markdown_text dan menulis file.

def write_page

Mari kita hancurkan ini juga. Untuk setiap posting, saya membutuhkan format tertentu: sesuatu seperti 2016-10-25-Avdi-Grimm-120. Saya ingin menulis file yang dimulai dengan tanggal dan menyertakan nama yang diwawancara dan nomor episode.

Untuk mencocokkan format Middleman mengharapkan untuk posting baru, saya perlu mengambil nama yang diwawancarai dan memasukkannya melalui metode helper saya untuk dasherize nama untuk saya, dari Avdi Grimm ke Avdi-Grimm. Tidak ada yang ajaib, tapi layak dilihat:

def dasherize

Ini menghapus spasi dari teks yang kita gesek untuk nama yang diwawancarai dan menggantikan ruang putih antara Avdi dan Grimm dengan tanda hubung. Sisa nama file diputuskan bersama-sama dalam string itu sendiri: "date-interviewee-name-episodenumber".

def write_page

Karena isi diekstraksi berasal langsung dari situs HTML, saya hanya tidak dapat menggunakan .md atau .markdown sebagai ekstensi nama file. Saya memutuskan untuk menggunakan .html.erb.md. Untuk episode mendatang yang saya tulis tanpa tergores, saya dapat meninggalkan bagian .html.erb dan hanya perlu .md.

Setelah langkah ini, loop dalam fungsi scrape berakhir, dan kita harus memiliki satu episode yang terlihat seperti ini:

2014-12-01-Avdi-Grimm-1.html.erb.md

Scraper ini akan mulai pada episode terakhir, tentu saja, dan loop sampai yang pertama. Untuk tujuan demonstrasi, episode 01 sebagus apa pun. Anda dapat melihat di bagian atas masalah depan dengan data yang kami ekstrak.

Semua itu sebelumnya terkunci dalam database aplikasi Sinatra saya—nomor episode, tanggal, nama orang yang diwawancara, dan seterusnya. Sekarang kami siap untuk menjadi bagian dari situs baru saya di Harvard Middleman. Segala sesuatu di bawah dua garis tiga (---) adalah teks dari catatan acara: pertanyaan dan tautan sebagian besar.

Pikiran Akhir

Dan kita selesai. Podcast baru saya sudah aktif dan berjalan. Saya benar-benar senang saya meluangkan waktu untuk mendesain ulang sesuatu dari bawah ke atas. Jauh lebih keren untuk mempublikasikan episode baru sekarang. Menemukan konten baru harus halus untuk pengguna juga.

Seperti yang saya sebutkan sebelumnya, ini adalah waktu dimana Anda harus pergi ke editor kode Anda untuk memiliki beberapa menyenangkan. Ambil kode ini dan bergumul dengan itu sedikit. Mencoba untuk menemukan cara untuk membuatnya sederhana. Ada beberapa kesempatan untuk refactor kode.

Secara keseluruhan, saya berharap contoh kecil ini memberi Anda ide yang baik dari apa yang dapat Anda lakukan dengan web baru scraping daging. Tentu saja Anda dapat mencapai tantangan yang jauh lebih canggih—saya yakin ada banyak peluang bisnis kecil yang harus dibuat dengan keterampilan ini.

Tapi seperti biasa, mengambil satu langkah pada satu waktu, dan jangan terlalu frustrasi jika hal-hal tidak mengklik segera. Hal ini tidak hanya normal bagi kebanyakan orang tetapi untuk diharapkan. Itu bagian dari perjalanan. Happy scraping!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.