Cara menggunakan web scraping python course

Indonesian (Bahasa Indonesia) translation by Aditia Dwiperdana (you can also view the original English article)

Pada tutorial sebelumnya, saya memperlihatkan bagaimana cara menggunakan modul Requests untuk mengakses halaman web menggunakan Python. Tutorial tersebut membahas banyak topik seperti membuat request GET/POST dan mengunduh benda seperti gambar atau PDF menggunakan pemrograman. Satu hal yang tidak ada di tutorial tersebut adalah panduan untuk menyimpan halaman web yang kamu akses menggunakan Request untuk mengambil informasi yang kamu butuhkan.

Pada tutorial ini kamu akan belajar tentang Beautiful Soup, library Python untuk mengambil data dari file HTML. Fokus tutorial ini adalah mempelajari dasar-dasar dari library tersebut, dan topik lanjutan akan dibahas pada tutorial berikutnya. Perlu diketahui tutorial ini menggunakan Beautiful Soup 4 untuk semua contoh.

Instalasi

Kamu bisa menginstall Beautiful Soup 4 menggunakan pip. Package namenya beautifulsoup4. Seharusnya bisa bekerja untuk Python 2 dan Python 3.

$ pip install beautifulsoup4

Jika kamu tidak punya pip, kamu bisa mengunduh source tarball Beautiful Soup 4 dan menginstallnya menggunakan setup.py.

$ python setup.py install

BeautifulSoup awalnya di-package sebagai kode Python 2. Saat kamu menginstallnya dengan Python 3, akan secara otomatis diupdate menjadi kode Python 3. Kode tidak akan diubah kecuali kamu menginstall package-nya. Berikut ada beberapa kesalahan umum yang mungkin akan kamu temui:

  • ImportError "No module named HTMLParser" terjadi jika kamu menjalankan kode versi Python 2 pada Python 3.
  • ImportError "No module named html.parser" terjadi jika kamu menjalankan kode versi Python 3 pada Python 2.

Kedua error tersebut bisa diperbaiki dengan uninstall dan install ulang Beautiful Soup.

Menginstall Parser

Sebelum membahas perbedaan antar berbagai parser yang berbeda yang bisa kamu gunakan dengan Beautiful Soup, mari buat kode untuk membuat sebuah soup.

from bs4 import BeautifulSoup

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html.parser")

Objek BeautifulSoup bisa menerima dua argumen. Pertama adalah markup yang ingin diproses, kedua adalah parser yang ingin kamu gunakan. Beberapa contoh parser diantaranya: html.parser, lxml, dan html5lib. Parser lxml memiliki dua versi, parser HTML dan parser XML.

html.parser adalah parser bawaan, dan tidak bisa bekerja dengan baik di Python versi lama. Kamu bisa menginstall parser lain dengan perintah berikut:

$ pip install lxml
$ pip install html5lib

Parser lxml sangat cepat dan bisa digunakan untuk mengolah HTML dengan cepat. Di sisi lain, html5lib sangat lambat, tapi sangat fleksibel. Berikut adalah contoh penggunaan masing-masing parser:

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html.parser")
print(soup)
# <html><p>This is <b>invalid HTML</b></p></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "lxml")
print(soup)
# <html><body><p>This is <b>invalid HTML</b></p></body></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "xml")
print(soup)
# <?xml version="1.0" encoding="utf-8"?>
# <html><p>This is <b>invalid HTML</b></p></html>

soup = BeautifulSoup("<html><p>This is <b>invalid HTML</p></html>", "html5lib")
print(soup)
# <html><head></head><body><p>This is <b>invalid HTML</b></p></body></html>

Perbedaan yang digambarkan di atas hanya penting jika kamu mengolah HTML yang tidak valid. Tapi, sebagian besar HTML di web tidak memiliki format yang benar, dan mengetahui perbedaan ini akan membantu kamu saat mendebug parsing error dan menentukan parser mana yang ingin kamu gunakan dalam project. Secara umum, parser lxml adalah pilihan yang sangat baik.

Objek pada Beautiful Soup

Beautiful Soup mengurai dokumen HTML yang diberikan menjadi pohon berisi objek Python. Ada empat objek Python utama yang kamu perlu ketahui: Tag, NavigableString, BeautifulSoup,  dan Comment.

Objek Tag mengacu pada tag XML atau HTML dalam dokumen. Kamu bisa mengakses nama sebuah tag menggunakan tag.name. Kamu juga bisa mengubah nama tag. Perubahan nama akan terlihat pada markup yang dihasilkan oleh Beautiful Soup.

Kamu bisa mengakses berbagai atribut berbeda seperti kelas dan is dari tag menggunakan tag['class'] dan tag['id']. Kamu juga bisa mengakses keseluruhan kamus atribut menggunakan tag.attrs. Kamu juga bisa menambah, menghapus, atau mengubah atribut sebuah tag. Atribut seperti class sebuah elemen yang bisa menyimpan banyak nilai disimpan sebagai list.

Teks dalam sebuah tag disimpan sebagai NavigableString dalam Beautiful Soup. Terdapat beberapa fungsi berguna seperti replace_with("string") untuk mengganti teks dalam tag. Kamu juga bisa mengubah NavigableString menjadi unicode string menggunakan unicode().

Beautiful Soup juga membolehkan kamu mengakses komentar dalam halaman web. Komen tersebut disimpan sebagai objek Comment, yang merupakan sebuah NavigableString.

Kamu sudah belajar tentang objek BeautifulSoup di bagian sebelumnya. Objek tersebut digunakan untuk mewakili keseluruhan dokumen. Karena bukan merupakan sebuah objek sebenarnya, objek ini tidak memiliki nama atau atribut.

Mengambil Judul, Heading, dan Tautan

Kamu bisa mengekstrak judul halaman dan data lain dengan mudah menggunakan Beautiful Soup. Mari scrape halaman Wikipedia tentang Python. Pertama, kamu perlu mengambil markup dari halaman menggunakan kode dari tutorial modul Requests untuk mengakses halaman web.

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")

Setelah membuat soup, sekarang kamu bisa mendapat judul halaman web dengan kode berikut:

soup.title
# <title>Python (programming language) - Wikipedia</title>

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'

Kamu juga bisa mengorek halaman web untuk informasi lain seperti judul bab atau paragraf pertama, kelas mereka, atau atribut id-nya.

soup.h2
# <h2 class="firstHeading" id="firstHeading" lang="en">Python (programming language)</h2>

soup.h2.string
# 'Python (programming language)'

soup.h2['class']
# ['firstHeading']

soup.h2['id']
# 'firstHeading'

soup.h2.attrs
# {'class': ['firstHeading'], 'id': 'firstHeading', 'lang': 'en'}

soup.h2['class'] = 'firstHeading, mainHeading'
soup.h2.string.replace_with("Python - Programming Language")
del soup.h2['lang']
del soup.h2['id']

soup.h2
# <h2 class="firstHeading, mainHeading">Python - Programming Language</h2>

Begitu pula kamu bisa mengiterasi semua link atau subjudul dalam dokumen menggunakan kode berikut:

for sub_heading in soup.find_all('h2'):
    print(sub_heading.text)
    
# all the sub-headings like Contents, History[edit]...

Kamu bisa menjelajah di dalam DOM tree menggunakan nama tag biasa. Merantaikan nama tag bisa membantu kamu menjelajah lebih dalam. Contohnya, kamu bisa mendapatkan link pertama di paragraf pertama di halaman Wikipedia tersebut menggunakan soup.p.a. Semua link di paragraf pertama bisa diakses menggunakan soup.p.find_all('a').

Kamu juga bisa mengakses semua anak dari sebuah tag sebagai list dengan menggunakan tag.contents. Untuk mendapatkan anak dengan indeks tertentu, kamu bisa gunakan tag.contents[index]. Kamu juga bisa mengiterasi anak-anak dari tag menggunakan atribut .children.

.children dan .contents berguna ketika kamu ingin mengakses langsung atau keturunan pertama dari sebuah tag. Untuk mendapatkan semua keturunan, kamu bisa menggunakan atribut .descendants.

print(soup.p.contents)
# [<b>Python</b>, ' is a widely used ',.....the full list]

print(soup.p.contents[10])
# <a href="/wiki/Readability" title="Readability">readability</a>

for child in soup.p.children:
    print(child.name)
# b
# None
# a
# None
# a
# None
# ... and so on.

Kamu juga bisa mengakses orang tua dari elemen menggunakan atribut .parent. Begitu pula kamu bisa mengakses semua leluhur elemen menggunakanatribut  .parents. Orang tua dari tag <html> adalah objek BeautifulSoup itu sendiri, dan orang tuanya adalah None.

print(soup.p.parent.name)
# div

for parent in soup.p.parents:
    print(parent.name)
# div
# div
# div
# body
# html
# [document]

Kamu bisa mengakses elemen saudara sebelum dan sesudah menggunakan atribut .previous_sibling dan .next_sibling.

Untuk dua elemen menjadi saudara, mereka harus memiliki orang tua yang sama. Artinya anak pertama dari elemen tidak akan memiliki saudara sebelumnya. Begitu pula, anak terakhir dari sebuah elemen tidak akan punya saudara berikutnya. Dalam halaman web sebenarnya, saudara sebelum dan berikutnya dari sebuah elemen kemungkinan besar adalan karakter ganti baris.

Kamu juga bisa mengiterasi semua saudara sebuah elemen menggunakan .previous_siblings dan .next_siblings.

soup.head.next_sibling
# '\n'

soup.p.a.next_sibling
# ' for '

soup.p.a.previous_sibling
# ' is a widely used '

print(soup.p.b.previous_sibling)
# None

Kamu bisa pindah ke elemen setelah elemen ini menggunakan atribut .next_element. Untuk mengakses elemen sebelumnya, gunakan atribut .previous_element.

Begitu pula kamu bisa mengiterasi semua elemen sebelum dan sesudah sebuah elemen menggunakan .previous_elements dan .next_elements.

Penutup

Setelah menyelesaikan tutorial ini, kamu sudah mengetahui perbedaan utama antar berbagai parser HTML. Kamu juga seharusnya sudah bisa menjelajah halaman web dan mengambil data penting. Hal ini bisa berguna ketika kamu ingin menganalisis semua judul bagian atau tautan dari sebuah situs web.

Pada bagian berikutnya dari seri ini, kamu akan belajar bagaimana menggunakan library Beautiful Soup untuk mencari dan memodifikasi DOM.