1. Home
  2. Docs
  3. Kelas Privat Python – 01
  4. Materi [Penerapan Python]
  5. Webscraping

Webscraping

Secara harfiah, webscraping, seperti pada namanya web dan scraping memiliki arti “Mengeruk ke dalam web”, puitis sekali bukan (smile). Secara praktikal, pengertiannya adalah mengambil data pada situs internet secara langsung dengan memanfaatkan struktur situs tersebut.
sumber : prowebscraper.com/blog/wp-content/uploads/2017/11/What_is_Web_Scraping.png
Beberapa Langkah yang harus kita lakukan saat akan melakukan pengambilan/scraping data pada situs web adalah
  • Request response
  • Inspect halaman
  • Parse dan ekstrak data yang kita inginkan
  • Simpan data ke dalam fotmat yang kita inginkan

Legalitas?

Saat kita akan melakukan pengerukan data pada suatu situs tentu saja ada kemungkinan situs tersebut memiliki data yang dilindungi hukum atau merupakan data yang berhubungan dengan privasi. Apakah legal untuk melakukan pengambilan data menggunakan pada situs tersebut? Sayangnya ini masih menjadi sebuah pertanyaan yang belum jelas jawaban pastinya, karena pada umumnya menampilkan data di internet seperti memberikan akses untuk khalayak umum. Beberapa poin di bawah akan menjelaskan sedikit tentang legalitas.
  • Ambil data publik sebanyak yang kamu inginkan. Data publik seperti wikipedia merupakan relatif lebih aman untuk dilakukan pengambilan.
  • Lakukan pengambilan secara wajar, lalu hindari penggunaan data untuk keperluan komersial.
  • Penggunaan data dengan copyright untuk tujuan komersial, tidaklah etis dan termasuk ilegal. Ada baiknya bila terdapat copyright tanyakan secara pribadi apakah data tersebut bisa diambil atau tidak.
  • Selalu perhatikan Terms of Service (ToS) jika ada
  • Jika kalian menggunakan API seandainya disediakan, maka itu merupakan cara legal untuk melakukan pengambilan data.
  • Berikan jarak pada pengambilan data kalian, misalnya 1 request per 15 detik.

HTML DASAR

HTML adalah singkatan dari Hypertext Markup Language. HTML memungkinkan seseorang untuk membangun sebuah halaman situs dengan menggunakan struktur kode sederhana. Ingat, HTML bukanlah merupakan suatu bahasa pemograman. Kemampuan untuk memahami kode HTML dasar sangat penting untuk melakukan scraping dikarenakan hal tersebut yang akan menjadi kunci pencarian saat kita akan mengambil data yang kita butuhkan. HTML dibangun oleh beberapa elemen seperti paragraf, image, dan judul, layaknya kita menulis dengan menggunakan perangkat lunak pengolah kata.Element pada HTML tersebut biasanya di tuliskan dengan tag pembuka dan penutup yang menggunakan kode <tag></tag>.
<!DOCTYPE html>  
<html>  
    <head>
    </head>
    <body>
        <p> Hello World </p>
    <body>
</html
Kode di atas adalah kode dasar HTML yang sering digunakan saat beberapa orang belajar tentang HTML: 1. <!DOCTYPE html>: Deklarasi pertama bahwa itu tipe dokumen HTML. 2.  Diantara tag <html> dan </html> digunakan untuk menyimpan semua kode yang akan kita tulis 3. Kode yang ingin kita simpan tapi tidak tampilkan, misal script yang kita buat. Maka ditaruh diantara tag <head>dan </head>. 4. Bagian yang ingin kita tampilkan kita tulis diantara tag <body>  dan  </body>. 5. <p> digunakan untuk memulai suatu paragraf . Tag <head> dan <body> merupakan tag yang setara (sibling) karena keduanya berada di bawah tag <html> sedangkan tag <html> sendiri merupakan parent dari tag <head> dan <body>. Selain tags kita juga harus mengenal dua properti yang biasanya dimiliki oleh sebuah tag, yaitu class dan id. Bukan merupakan kewajiban properti ini ada, tapi dengan properti ini kita bisa mengidentifikasi dengan lebih mudah suatu elemen dalam html. Sebuah elemen dapat memiliki beberapa class, dan satu class dapat disematkan kedalam beberapa elemen. Akan tetapi, setiap elemen hanya dapat memiliki satu id unik. Ada beberapa hal yang harus kita ingat saat ingin melakukan web scraping. pertama kita harus tahu apakah website yang kita ingin ambil datanya memperbolehkan kita untuk hal tersebut? jika iya apakah data tersebut boleh digunakan untuk keperluan komersil atau hanya pengunaan pribadi. Salah satu website yang bisa kita gunakan untuk latihan adalah wikipedia.

Langkah – Langkah

  1. Import semua library yang dibutuhkan
  2. tentukan alamat yang ingin kita buka, lalu akses dengan menggunakan request atau urlopen
  3. Masukkan dalam Metode beautifulsoup
  4. Inspeksi Halaman Web
  5. Ambil class dan/atau id elemen html yang kita inginkan
  6. Gunakan metode find atau findall untuk mengambil data

Beautifulsoup4

Ada beberapa library atau modul yang bisa digunakan untuk melakukan web scraping, diantaranya:
  • Request
  • BeautifulSoup4
  • lxml
  • Selenium
  • Scrapy
Yang akan kita bahas kali ini adalah BeautifulSoup. BeautifulSoup merupakan library python digunakan untuk melakukan web scraping dalam package bs4. Untuk menginstall bs4 bisa menggunakan pip atau conda.
pip install beautifulsoup4
Kita import libray yang kita butuhkan,
from urllib.request import urlopen
from bs4 import BeautifulSoup
  • urllib.request digunakan untuk membuka url yang akan ambil datanya
  • bs4 merupakan library yang kita gunakan untuk memanggil atau menggunakan BeautifulSoup untuk mengambil data dari HTML.
alamat = "https://blog.sanbercode.com/"
html = urlopen(alamat)
data = BeautifulSoup(html, 'html.parser')
Pada bagian alamat kita bisa ubah menjadi website yang kita inginkan tapi ingat, tidak semua website memperbolehkan bot untuk melakukan akses. Sebelum memulai untuk mangambil data kita harus menentukan pada bagian mana kita akan mengambil datanya. Seperti yang disebutkan pada bagian sebelumnya, mengerti HTML dan komponen di dalamnya sangat penting. Kita ambil contoh kita akan mencoba mengambil data di website blog.sanbercode
Misal kita akan mengambil kata-kata Mengenal Dunia Programming, maka kita bisa melakukan inspeksi komponen html dengan cara klik kanan pada tulisan tersebut.
Setelah kita klik maka akan muncul halaman inspeksi, lalu dari halaman tersebut kita mendapatkan tag <a> dan class = “text-dark”. Maka data tersebut dapat kita masukan pada kode selanjutnya
items = data.findAll("a", {"class":"text-dark"})
findAll digunakan untuk mencari semua tags “a” dan class “text-dark” pada halaman tersebut. Jika kita hanya ingin mengambil data dari tag pertama yang ditemukan oleh sistem, maka gunakanlah find().
items = data.find("a", {"class":"text-dark"})
jika kita uji dengan menggunakan print (items) maka akan kita dapatkan hasil,
print (items)
print (len(items))
[<a class="text-dark" href="https://blog.sanbercode.com/mengenal-dunia-programming/">
                Mengenal dunia Programming</a>, <a class="text-dark" href="https://blog.sanbercode.com/implementasi-debugging-tools-telescope-di-laravel/">
                Implementasi Debugging Tools Telescope di Laravel</a>, <a class="text-dark" href="https://blog.sanbercode.com/facebook-login-tutorial-dengan-laravel-5-7-dan-socialite/">
                Facebook Login Tutorial dengan Laravel 5.7 dan Socialite</a>, <a class="text-dark" href="https://blog.sanbercode.com/agile-software-development-sebuah-pengenalan/">
                Agile Software Development, Sebuah Pengenalan</a>, <a class="text-dark" href="https://blog.sanbercode.com/knowledge-management-apa-sih/">
                Knowledge Management, Apa sih?</a>, <a class="text-dark" href="https://blog.sanbercode.com/server-upload-file-ke-google-drive-via-command-line/">
                Server upload file ke google drive via command line</a>, <a class="text-dark" href="https://blog.sanbercode.com/mockup-ui/">
                Mockup UI</a>, <a alt="View all posts in Backend" class="text-dark" href="https://blog.sanbercode.com/category/backend/">Backend</a>, <a alt="View all posts in Devops" class="text-dark" href="https://blog.sanbercode.com/category/devops/">Devops</a>, <a alt="View all posts in Frontend" class="text-dark" href="https://blog.sanbercode.com/category/frontend/">Frontend</a>, <a alt="View all posts in Info" class="text-dark" href="https://blog.sanbercode.com/category/info/">Info</a>, <a alt="View all posts in Management and Support" class="text-dark" href="https://blog.sanbercode.com/category/management-and-support/">Management and Support</a>, <a class="text-dark" href="https://blog.sanbercode.com/server-upload-file-ke-google-drive-via-command-line/">
                        Server upload file ke google drive via command line</a>, <a class="text-dark" href="https://blog.sanbercode.com/telegram-notification-channel-via-laravel-5-8/">
                        Telegram Notification Channel via Laravel 5.8</a>, <a class="text-dark" href="https://blog.sanbercode.com/mockup-ui/">
                        Mockup UI</a>, <a class="text-dark" href="https://blog.sanbercode.com/knowledge-management-apa-sih/">
                        Knowledge Management, Apa sih?</a>, <a class="text-dark" href="https://blog.sanbercode.com/agile-software-development-sebuah-pengenalan/">
                        Agile Software Development, Sebuah Pengenalan</a>]

17
Terdapat terlalu banyak data yang didapatkan, artinya banyak komponen html yang memiliki tag dan class yg sama. Jika kita lihat maka kita tahu ada 17 isi dari variabel items yang kita tahu ternyata adalah list. Karena hasil scrap adalah list artinya kita dapat mengambil data yang kita butuhkan dengan memberikan indeks pada variabel items. Mengenal Dunia Programming berada pada urutan pertama, artinya indeks nomor 0 maka kita tulis kembali persamaannya menjadi,
items = data.findAll("a", {"class":"text-dark"})[0]
print (items)
akan didapatkan hasil seperti ini,
<a class="text-dark" href="https://blog.sanbercode.com/mengenal-dunia-programming/">
                Mengenal dunia Programming</a>
Masih belum berbentuk seperti yang kita inginkan, yang dapat kita lakukan adalah kita bisa mengambil hanya kompenen teks dalam tag “a” tersebut dengan menambahkan get_text()
items = data.findAll("a", {"class":"text-dark"})[0]
print (items.get_text())
Akhirnya kita dapatkan teks yang kita inginkan, dari sedikit contoh ini kita tahu bahwa sangat penting untuk mengerti struktur dari html untuk dapat melakukan scraping data dari web yang kita inginkan. Kode Lengkapnya dapat dilihat di bawah ini
from urllib.request import urlopen
from bs4 import BeautifulSoup

alamat = "https://blog.sanbercode.com/"
html = urlopen(alamat)
data = BeautifulSoup(html, 'html.parser')

items = data.findAll("a", {"class":"text-dark"})
for item in items:
    print (item.get_text())

Mengambil data Wikipedia

Sebelum bermain dengan data pada wikipedia, kita akan mengenal lebih jauh tentang beautifulsoup dan metode yang terkandung di dalamnya. Pertama kita akan menyiapkan variabel html kita

html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""
Lalu kita ambil data tersebut menggunakan library beautifulsoap
from bs4 import BeautifulSoup
data = BeautifulSoup(html_doc, 'html.parser')

Filter

Pada kesempatan sebelumnya kita mengetahui bahwa filter yang kita gunakan dalam metode pencarian adalah filter string terhadap tag html yang kita cari. Pada kenyataannya terdapat beberapa filter yang dapat kita pakai.

String

Seperti yang kita tahu, saat kita menggunakan string maka beautifulsoap akan mencari tag pada html yang memiliki nilai persis dengan string tersebut
data.find_all('b')
#[<b>The Dormouse's story</b>]

Regular Expression

Jika tidak memiliki spesifik tag yang akan kita cari maka kita bisa memanfaatkan regular expression (regex) untuk mencari tag dengan awalan, akhiran, atau mengandung syarat yang kita tentukan. Kode dibawah akan mengembalikan semua tag yang diawali oleh huruf b.
import re
data.find_all(re.compile("^b"))

#[<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body>, <b>The Dormouse's story</b>]

List

List digunakan jika kita menginginkan pencarian pada lebih dari satu tag. beautifulsoap akan melakukan pencarian dengan semua parameter kata kunci pada list.
data.find_all(["a", "b"])
# [<b>The Dormouse's story</b>,
#  <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

Search & Navigasi

find_parents() and find_parent()

Pada umumnya, pencarian menggunakan find dan findAll/find_all akan memberikan hasil pencarian pada children tag/ ke arah bawah dari data kita. find_parent akan melakukan pencarian sebaliknya yaitu naik. kita navigasikan data kita terlebih dahulu.
data = bs(html_doc, 'html.parser')
data_baru = data.find('p')
print (data_baru)
#<p class="title"><b>The Dormouse's story</b></p>
Lalu kita akan coba mencari tag yang berada di atas tag <p> tersebut
data_2 = data_baru.find_parent()
print(data_2)
#<body>
#<p class="title"><b>The Dormouse's story</b></p>
#<p class="story">Once upon a time there were three little #sisters; and their names were
#<a class="sister" href="http://example.com/elsie" #id="link1">Elsie</a>,
#<a class="sister" href="http://example.com/lacie" #id="link2">Lacie</a> and
#<a class="sister" href="http://example.com/tillie" #id="link3">Tillie</a>;
#and they lived at the bottom of a well.</p>
#<p class="story">...</p>
#</body>

find_next_sibling() and find_previous_sibling()

find_next_sibling() digunakan untuk mencari tag apa yang ada setelah tag <p>. find_previous_sibling() digunakan untuk mencari tag apa yang ada sebelum tag <p>. tag yang dicari merupakan tag yang memiliki level yang sama.
data = bs(html_doc, 'html.parser')
data_baru = data.find('p')
data_2 = data_baru.find_next_sibling()

print(data_2)

#<p class="story">Once upon a time there were three little #sisters; and their names were
#<a class="sister" href="http://example.com/elsie" #id="link1">Elsie</a>,
#<a class="sister" href="http://example.com/lacie" #id="link2">Lacie</a> and
#<a class="sister" href="http://example.com/tillie" #id="link3">Tillie</a>;
#and they lived at the bottom of a well.</p>

.contents

Contents digunakan untuk mencari content atau tag apa saja yang berada di dalam tag yang kita tentukan. ini digunakan jika kita ingin mengambil parameter dari tag tersebut dan mengembalikannya dalam bentuk list.
data = bs(html_doc, 'html.parser')
data_baru = data.findAll('p')[1]

print(data_baru)

#<p class="story">Once upon a time there were three little #sisters; and their names were
#<a class="sister" href="http://example.com/elsie" #id="link1">Elsie</a>,
#<a class="sister" href="http://example.com/lacie" #id="link2">Lacie</a> and
#<a class="sister" href="http://example.com/tillie" #id="link3">Tillie</a>;
#and they lived at the bottom of a well.</p>
Sekarang kita akan coba ambil semua contents dalam tag tersebut.
data_2 = data_baru.contents
print(data_2)

#['Once upon a time there were three little sisters; and their names were\n', <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, ',\n', <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, ' and\n', <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>, ';\nand they lived at the bottom of a well.']

#atau

for item in data_2:
    print(item)

#Once upon a time there were three little sisters; and their names #were
#
#<a class="sister" href="http://example.com/elsie" #id="link1">Elsie</a>
#,
#
#<a class="sister" href="http://example.com/lacie" #id="link2">Lacie</a>
# and
#
#<a class="sister" href="http://example.com/tillie" #id="link3">Tillie</a>
#;
#and they lived at the bottom of a well.

Bermain dengan Wikipedia

Salah satu situs yang dapat menjadi sumber data eksternal data analis adalah wikipedia. wikipedia juga merupakan sumber yang baik untuk kita melatih untuk dapat “menangkap” data karena berbagai jenis data yang dimiliki. Kali ini kita akan mencoba untuk mengambil data tabel yang ada di wikipedia.

Persiapan yang dilakukan sama seperti yang kita lakukan pada materi sebelumnya, pertama kita import library yang dibutuhkan.

from urllib.request import urlopen
from bs4 import BeautifulSoup

Ketikkan kode utama yang akan kita gunakan, sebagai contoh kita akan mencoba mengambil tabel List of Brightest Stars

alamat = "https://en.wikipedia.org/wiki/List_of_brightest_stars"
html = urlopen(alamat)
data = BeautifulSoup(html, 'html.parser')

Sama seperti sebelumnya, kita coba inspeksi halaman situs untuk mendapatkan elemen yang kita butuhkan.

Kita dapatkan tag “table dengan class “wikitable” . Kita gunakan kedua informasi tersebut sebagai variabel pencarian kita.

table = data.findAll("table", {"class":"wikitable"})

Cara yang kita lakukan untuk mengambil semua data dalam tabel tersebut adalah kita ambil perbaris lalu bergerak ambil tiap sel dari baris tersebut. Kita dapatkan untuk baris tag yang digunakan adalah “tr” maka kodenya dapat kita ketikkan,

table = data.findAll("table", {"class":"wikitable"})[0]
rows = table.findAll("tr")

Karena kita memiliki banyak baris dalam satu tabel dan banyak kolom/sel dalam satu baris maka kita akan menggunakan perulangan atau looping untuk mendapatkan datanya. Masalahnya, jika kita inspeksi lebih lanjut ternyata dalam tabel kita terdapat dua jenis tag kolom untuk judul dan isi seperti yang diperlihatkan gambar dibawah.

kolom/sel judul
kolom/sel isi

Untuk judul menggunakan tag “th”, untuk isi menggunakan tag “td”. Sedangkan materi selama ini findAll yang kita gunakan hanya menggunakan satu tag. Apakah kita harus membuat dua statement findAll? Jawabannya adalah kita dapat menggunakan kurung siku “[]” sebagai solusi. Dengan berkaca pada kedua hal diatas maka kode yang akan tuliskan menjadi,

table = data.findAll("table", {"class":"wikitable"})[0]
rows = table.findAll("tr")
for row in rows:
    for cell in row.findAll(["td", "th"]):
         print(cell.get_text())

Memasukkan Hasil Akhir pada List

Jika sebelumnya kita menggunakan print, maka kali ini kita akan mencoba menyimpan data kita pada sebuah list. Caranya cukup mudah untuk dilakukan. kita hanya perlu menentukan variabel kosong yang dideklarasikan sebagai list. karena kita memiliki dua perulangan maka kita membutuhkan dua variabel kosong, yang pertama untuk menyimpan satu beberapa sel menjadi baris dan yang kedua untuk menyimpan beberapa baris menjadi tabel. Setiap satu variabel kosong ditulis diluar satu loop. Setelah itu kita gunakan metode append untuk menuliskan data kita pada list tersebut.

hasil = []
for row in rows:
    info = []
    for cell in row.findAll(["td", "th"]):
        info.append(cell.get_text())
    hasil.append(info)

Jika kita lakukan perintah print maka kita akan dapat melihat hasil yang telah kita dapatkan. Sekian materi untuk kesempatan kali ini. Pada hari selanjutnya kita akan membahas tentang bagaimana jika kita akan melakukan web scraping dari situs lain, misal situs data atau harga.

Sumber bacaan eksternal:

https://ngodingdata.com/tutorial-web-scraping-dengan-beautifulsoup-di-python-part-1/
https://www.crummy.com/software/BeautifulSoup/bs4/doc/ Scraping Data Tabel HTML Wikipedia (with Python) https://hkalabs.com/scraping-data-tabel-html-wikipedia-with-python/embed/#?secret=WwCaQrGfAN https://simpleanalytical.com/how-to-web-scrape-wikipedia-python-urllib-beautiful-soup-pandas https://towardsdatascience.com/step-by-step-tutorial-web-scraping-wikipedia-with-beautifulsoup-48d7f2dfa52d