Data tabel yang kita butuhkan sering kali sudah tersaji di halaman web: rekap statistik resmi, daftar harga komoditas, jadwal transportasi, atau laporan internal yang ditampilkan lewat aplikasi perusahaan. Menyalin-tempel tabel semacam itu ke spreadsheet memakan waktu, mudah salah, dan tidak bisa diulang secara otomatis. Fungsi pd.read_html() menyelesaikan masalah ini dengan memindai semua elemen <table> di dalam dokumen HTML, lalu mengubah setiap tabel menjadi DataFrame yang siap dianalisis. Chapter ini membahas cara kerja read_html(), mencobanya pada string HTML tanpa jaringan, dan menutup dengan catatan praktis ketika tabel web tidak rapi.
Cara Kerja read_html() #
Fungsi read_html() menerima tiga jenis sumber secara bergantian: string berisi HTML (biasanya dibungkus io.StringIO), path file HTML lokal, atau URL halaman web. Pandas mencari seluruh elemen <table> di dokumen, memakai sel <th> sebagai nama kolom bila tabel memiliki baris header, dan menjadikan setiap baris data sebagai row DataFrame. Nilai kembalian selalu berupa list berisi DataFrame, bukan satu DataFrame, karena satu dokumen boleh memuat banyak tabel. Isi sel angka dikonversi otomatis menjadi int64 atau float64, sedangkan sel teks menjadi kolom bertipe str pada pandas 3.0.
Parser yang dipakai ditentukan parameter flavor: lxml sebagai pilihan default yang paling cepat, atau bs4 + html5lib yang paling toleran terhadap HTML tidak rapi. Bila parser yang dibutuhkan belum terpasang, pandas melempar ImportError beserta petunjuk library yang perlu diinstal. Dokumentasi resmi pandas.read_html
merinci semua parameter, dan halaman IO Tools
menempatkan read_html() dalam peta pembaca data pandas secara keseluruhan. Di lingkungan Course ini kedua parser sudah tersedia, sehingga contoh berikut bisa langsung dijalankan.
Membaca Tabel dari String HTML #
Agar contoh tetap runnable tanpa jaringan, kita memakai dokumen HTML kecil yang ditulis sebagai string lalu dibungkus io.StringIO. Dokumen latihan ini memuat dua tabel, masing-masing diberi judul lewat tag <caption>, sehingga kita bisa mengamati perilaku read_html() ketika ada lebih dari satu tabel sekaligus.
from io import StringIO
import pandas as pd
html_toko = """
<html>
<body>
<h1>Laporan Toko Segar Jaya</h1>
<table>
<caption>Stok Produk</caption>
<tr><th>produk</th><th>harga</th><th>stok</th></tr>
<tr><td>Kopi Gayo</td><td>85000</td><td>12</td></tr>
<tr><td>Teh Melati</td><td>32000</td><td>30</td></tr>
<tr><td>Gula Aren</td><td>24000</td><td>25</td></tr>
</table>
<table>
<caption>Penjualan Hari Ini</caption>
<tr><th>produk</th><th>terjual</th></tr>
<tr><td>Kopi Gayo</td><td>5</td></tr>
<tr><td>Teh Melati</td><td>9</td></tr>
</table>
</body>
</html>
"""
hasil = pd.read_html(StringIO(html_toko))
print("Jumlah tabel yang ditemukan:", len(hasil))
print()
df = hasil[0]
print(df)
print()
print(df.dtypes)
print()
df_penjualan = pd.read_html(StringIO(html_toko), match="Penjualan")[0]
print(df_penjualan)Output yang Dihasilkan:
Jumlah tabel yang ditemukan: 2
produk harga stok
0 Kopi Gayo 85000 12
1 Teh Melati 32000 30
2 Gula Aren 24000 25
produk str
harga int64
stok int64
dtype: object
produk terjual
0 Kopi Gayo 5
1 Teh Melati 9Baris demi baris, inilah yang terjadi pada skrip di atas:
- Baris 5-24 (
html_toko): string dokumen HTML berisi dua<table>; tag<caption>memberi judul setiap tabel dan ikut terbaca oleh pandas. - Baris 26-27 (
hasil = pd.read_html(...)): pandas mem-parse dokumen dengan parser defaultlxml, menemukan 2 tabel, dan mengembalikan list berisi 2 DataFrame. - Baris 30-33 (
df = hasil[0]): tabel pertama dipilih lewat indexing list; kolomprodukbertipestr, sedangkan kolomhargadanstokotomatis menjadiint64. - Baris 36-37 (
match="Penjualan"): parametermatchmemfilter tabel berdasarkan pola teks di dalamnya, termasuk caption, sehingga hanya tabel Penjualan Hari Ini yang dikembalikan.
Parameter yang Membantu Saat Tabel Web Berantakan #
Tabel di web nyata jarang sesempurna tabel latihan. Baris header bisa berada di tengah tabel, angka memakai titik sebagai pemisah ribuan, atau sel berisi catatan kaki. Parameter berikut sering menolong situasi tersebut:
| Parameter | Peran |
|---|---|
match | Memilih tabel yang teksnya cocok dengan pola tertentu |
header | Menentukan baris mana yang menjadi nama kolom |
index_col | Menjadikan satu kolom sebagai index DataFrame |
thousands | Menghapus pemisah ribuan, misalnya "." pada "15.000" |
skiprows | Melewati baris catatan sebelum data mulai |
flavor | Memilih parser lxml atau bs4 + html5lib |
Hasil inferensi tipe data juga bisa meleset. Kolom harga yang berisi "Rp15.000" akan dibaca sebagai teks, bukan angka, sehingga kita perlu membersihkannya setelahnya dengan method string seperti Series.str.replace(). Kebiasaan yang sehat adalah memeriksa df.dtypes segera setelah read_html() dan memperbaiki tipe sebelum masuk ke analisis.
Materi mengambil tabel dari halaman web mengantar kita pada pertanyaan yang lebih umum: bagaimana membaca data yang tidak berupa file di disk, melainkan alamat di internet. Chapter berikutnya membahas persis topik tersebut, yaitu membaca dataset langsung dari URL beserta cara menangani ketergantungan jaringannya dengan bijak.