Geonode logo
Geonode Team

Geonode Team

Dikemas kini: 7 Oktober 2026

Diterbitkan: 2 September 2026

Lembar Referensi Singkat XPath: Panduan dengan Contoh

XPath adalah bahasa kueri untuk menelusuri dokumen XML dan HTML. Bahasa ini memiliki inti yang ringkas namun memiliki banyak sekali cara untuk disalahgunakan. Ini adalah panduan referensi yang disusun sesuai kebutuhan Anda: dimulai dengan sintaksis, dilanjutkan dengan fungsi-fungsi yang perlu diketahui, kemudian pola-pola yang sering muncul, dan terakhir jebakan-jebakan yang perlu diwaspadai. Semua yang tercantum di sini adalah XPath 1.0, yang diimplementasikan oleh browser, Selenium, dan sebagian besar pustaka pengurai.

Catatan singkat mengenai siapa yang menulis ini. Kami adalah Geonode dan kami menjual proxy kepada orang-orang yang mengekstrak data, sehingga XPath lebih bersifat terkait dengan bisnis kami daripada menjadi bagian darinya. Peringatan pentingnya adalah bahwa masalah selektor dan masalah proxy sama sekali tidak mirip, dan mengacaukannya hanya akan membuang-buang waktu — permintaan yang diblokir akan menampilkan halaman tantangan atau status kesalahan, sedangkan ekspresi yang salah akan menampilkan halaman yang tampak normal namun hasilnya kosong. Jika HTML-nya ada dan XPath Anda tidak menemukan apa pun, berarti jaringan berfungsi dengan baik dan halaman ini adalah tempat yang tepat.

Sintaks Dasar

EkspresiMemilih
/html/body/divJalur absolut dari akar
//divElemen div apa pun di mana pun dalam dokumen
//div/pElemen p yang merupakan anak langsung dari div
//div//pElemen p pada kedalaman apa pun di dalam div
.Node konteks saat ini
..Orang tua dari node konteks
*Elemen apa pun
@hrefAtribut href
//@hrefSetiap atribut href dalam dokumen
text()Anak node teks dari node konteks
node()Node apa pun, termasuk teks dan komentar
//a | //linkGabungan — semua yang cocok dengan salah satu ekspresi

Perbedaan antara / dan // adalah hal yang perlu dipahami. Satu garis miring berarti "anak langsung"; dua garis miring berarti "keturunan pada kedalaman apa pun". //div/p tidak menemukan paragraf yang dibungkus dalam section; //div//p menemukannya.

Jalur absolut — /html/body/div[2]/div[1]/span — adalah hasil yang dihasilkan oleh fitur "salin XPath" di browser dan yang akan bermasalah pada perombakan desain berikutnya. Sebaiknya mulailah dari sesuatu yang dapat diidentifikasi dan navigasikan secara relatif.

Predikat

Tanda kurung siku digunakan untuk menyaring sekumpulan node. Di sinilah sebagian besar proses yang berguna berlangsung.

EkspresiMemilih
//div[1]div pertama di antara saudara-saudaranya, per induk
(//div)[1]div pertama di seluruh dokumen
//div[last()]div terakhir di antara saudara-saudaranya
//div[position() < 4]Tiga yang pertama
//a[@href]Tautan yang memiliki atribut href
//a[@href='/about']Tautan dengan href yang persis sama
//div[@class and @id]Elemen yang memiliki kedua atribut tersebut
//p[text()]Paragraf dengan setidaknya satu anak elemen teks
//div[p]Elemen div yang berisi setidaknya satu anak elemen p
//div[not(@hidden)]Elemen div tanpa atribut hidden
//td[.='42'][@class='qty']Dua predikat, diterapkan secara berurutan

** Perbedaan antara//div[1] dan (//div)[1] adalah kebingungan paling umum dalam XPath.** Yang pertama adalah predikat yang diterapkan per orang tua, sehingga memilih div pertama di bawah setiap orang tua yang memilikinya — berpotensi banyak node. Yang kedua mengumpulkan semua elemen div ke dalam himpunan node sesuai urutan dokumen dan mengambil yang pertama, yang tepatnya hanya satu node. Keduanya berguna; namun, keduanya tidak dapat digunakan secara bergantian.

Predikat dirangkai, dan masing-masing diterapkan pada hasil predikat sebelumnya. //td[@class='price'][1] berarti "yang pertama di antara sel-sel dengan kelas price", dibaca dari kiri ke kanan.

Sumbu

Sumbu digunakan untuk menavigasi relatif terhadap simpul konteks. Kebanyakan orang menggunakan tiga sumbu dan sesekali memerlukan sumbu lainnya.

SumbuMemilih
child::Anak langsung — default, biasanya diabaikan
descendant::Semua keturunan pada kedalaman apa pun
parent::Orang tua
ancestor::Semua leluhur hingga akar
ancestor-or-self::Leluhur ditambah simpul itu sendiri
following-sibling::Saudara kandung yang lebih muda
preceding-sibling::Saudara kandung yang lebih tua
following::Segala sesuatu setelahnya dalam urutan dokumen, kecuali keturunan
preceding::Segala sesuatu yang ada di depan, tidak termasuk leluhur
attribute::Atribut — disingkat sebagai @
self::Simbol itu sendiri

Empat di antaranya adalah sumbu terbalik — ancestor, ancestor-or-self, preceding, dan preceding-sibling — dan pada sumbu-sumbu tersebut, penomoran posisi berjalan mundur. preceding-sibling::p[1] adalah paragraf terdekat yang mendahului, bukan yang pertama dalam dokumen. Gunakan tanda kurung untuk mendapatkan urutan dokumen. Kami telah membahas hal ini secara mendetail dalam XPath preceding-sibling.

following dan preceding memiliki cakupan yang jauh lebih luas dan jauh lebih lambat daripada rekan-rekan sibling-nya, serta masing-masing mengecualikan leluhur dan keturunan. Gunakanlah hanya jika hubungan tersebut benar-benar longgar.

Fungsi String

Fungsi-fungsi andalan.

FungsiFungsi
contains(a, b)Benar jika a mengandung b sebagai substring
starts-with(a, b)Benar jika a dimulai dengan b
normalize-space(s)Memotong dan menggabungkan spasi kosong internal
string-length(s)Menghitung jumlah karakter
substring(s, start, len)Substring, diindeks mulai dari 1
substring-before(a, b)Semua teks sebelum kemunculan pertama b
substring-after(a, b)Semua teks setelah kemunculan pertama b
translate(s, from, to)Penggantian karakter per karakter
concat(a, b, ...)Menggabungkan string
string(node-set)Nilai string dari node pertama saja

Tiga catatan yang mencegah bug yang sebenarnya.

substring() menggunakan indeks 1. substring('hello', 1, 3) mengembalikhel. Semua orang pernah salah mengartikannya sekali.

normalize-space() sebaiknya menjadi wrapper default Anda untuk perbandingan teks apa pun. HTML asli ditampilkan dengan format rapi, sehingga nilai string sel seringkali berupa "\n In stock\n" alih-alih "In stock". Tanpa argumen, fungsi ini beroperasi pada node konteks.

Tidak ada ends-with(), tidak ada lower-case(), dan tidak ada ekspresi reguler dalam XPath 1.0. Untuk pengabaian huruf besar-kecil, translate() dengan huruf-huruf yang ditentukan secara eksplisit adalah solusi standar. Pustaka sisi server seperti lxml mendukung ekstensi EXSLT termasuk re:test(); sedangkan browser dan Selenium tidak mendukungnya.

Fungsi Numerik dan Boolean

FungsiFungsi
count(node-set)Jumlah simpul
position()Posisi simpul konteks
last()Ukuran himpunan simpul konteks
number(s)Mengonversi menjadi bilangan
sum(node-set)Menjumlahkan nilai-nilai numerik
round(), floor(), ceiling()Sesuai namanya
not(expr)Negasi boolean
boolean(expr)Mengonversi ke boolean
true(), false()Nilai boolean literal

Operator perbandingan adalah =, !=, <, >, <=, >=, dengan and dan or untuk kombinasi. Perhatikan bahwa dalam konteks XML, < harus di-escape menjadi &lt;, itulah sebabnya Anda terkadang melihat ekspresi ditulis dengan position() &lt; 4.

Sebuah hal yang perlu diketahui: membandingkan himpunan node dengan suatu nilai merupakan pengujian eksistensial. //p = 'Price' bernilai benar jika ada paragraf yang sama dengan "Price". Hal ini seringkali yang Anda inginkan di dalam predikat, namun hampir tidak pernah yang Anda inginkan pada tingkat atas.

Pola yang Sering Muncul

Ekspresi yang benar-benar berguna.

Mencocokkan kelas dengan tepat — contains(@class, 'btn')

juga mencocokkan btn-primary

dan unbtn

:

//div[contains(concat(' ', normalize-space(@class), ' '), ' btn ')]

Mencari nilai berdasarkan labelnya — kebutuhan ekstraksi yang paling umum:

//dt[normalize-space()='Price']/following-sibling::dd[1]
//th[normalize-space()='Weight']/following-sibling::td[1]
//td[preceding-sibling::td[1]='SKU']

Mencari baris berdasarkan sel, lalu mengambil kolom yang berbeda:

//tr[td[normalize-space()='SKU-1234']]/td[3]

Temukan wadah berdasarkan sesuatu di dalamnya:

//div[contains(@class,'card')][.//span[contains(., 'Sold out')]]

Temukan elemen pertama setelah judul:

//h2[normalize-space()='Specifications']/following-sibling::table[1]

Pencocokan teks tanpa membedakan huruf besar/kecil:

//p[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                          'abcdefghijklmnopqrstuvwxyz'), 'price')]

Kecualikan daripada sertakan — seringkali lebih jelas:

//tr[not(contains(@class,'header'))]
//li[not(contains(normalize-space(),'Advertisement'))]

Cocokkan salah satu dari dua jenis elemen:

//*[self::button or self::a][normalize-space()='Continue']

Lewati nilai kosong:

//td[string-length(normalize-space()) > 0]

Ekstrak atribut dari elemen yang cocok:

//a[normalize-space()='Download']/@href

Perangkap

Diurutkan berdasarkan seberapa sering hal ini menghabiskan waktu pengguna.

Konversi himpunan node ke string hanya mengambil node pertama. contains(//p, 'Price') mengonversi seluruh himpunan node //p menjadi string dengan mengambil paragraf pertama dan mengabaikan sisanya. Gunakan predikat per node sebagai gantinya: //p[contains(., 'Price')]. Ini adalah bug XPath yang paling umum.

. dan text() berbeda. Nilai string suatu elemen adalah gabungan dari semua node teks keturunannya; text() hanya mengembalikan anak node teks langsung, dan konversi ke string hanya mengambil yang pertama dari node-node tersebut. Gunakan . kecuali Anda secara khusus ingin mengecualikan konten bersarang.

Penomoran sumbu terbalik. preceding-sibling::td[1] adalah yang terdekat, bukan yang pertama.

Spasi kosong. //td[.='In stock'] gagal pada HTML yang diformat rapi. normalize-space() memperbaikinya.

Sensitivitas huruf besar/kecil. Segala sesuatu dalam XPath 1.0 sensitif terhadap huruf besar/kecil, termasuk nama elemen dalam dokumen XML.

Ruang nama default. Dalam XML dengan ruang nama default, //item tidak cocok dengan apa pun — Anda harus mendaftarkan prefiks dan menggunakannya. Parser HTML biasanya membebaskan Anda dari hal ini; parser XML tidak.

Jalur absolut dari alat pengembang browser. Jalur tersebut mengkodekan struktur yang tepat pada satu titik waktu tertentu dan akan rusak jika terjadi perubahan apa pun.

Pencocokan berlebihan dengan contains(). Mencocokkan "Price" juga akan mencocokkan "Historic Price". Gunakan normalize-space() = 'Price' jika Anda bermaksud mencari kesamaan.

Menyisipkan string yang tidak terpercaya. Menyisipkan masukan pengguna ke dalam ekspresi merupakan injeksi XPath. Gunakan pengikatan variabel jika perpustakaan Anda menyediakannya. XPath 1.0 tidak memiliki karakter pelarian untuk tanda kutip di dalam literal string, sehingga nilai yang mengandung kedua karakter kutip tersebut memerlukan concat().

XPath 1.0 versus Versi-Versi Selanjutnya

Perlu diketahui karena potongan kode yang Anda temukan di internet mungkin tidak berfungsi sesuai kebutuhan Anda.

XPath 1.0 adalah versi yang diimplementasikan oleh peramban melalui document.evaluate, yang digunakan oleh Selenium, dan yang disediakan oleh API umum lxml. XPath 1.0 memiliki fungsi-fungsi yang tercantum di atas dan tidak lebih dari itu.

XPath 2.0 dan 3.1 menambahkan ekspresi reguler (matches(), replace()), fungsi kasus (upper-case(), lower-case()), ends-with(), tipe urutan, ekspresi for, dan banyak lagi. Fitur-fitur ini tersedia di pemroses XSLT 2.0+ dan beberapa alat XML, namun tidak tersedia di peramban.

Aturan praktis: jika suatu ekspresi menggunakan fungsi yang tidak tercantum dalam tabel di atas, periksa apakah lingkungan Anda mendukungnya sebelum menelusuri penyebab kegagalan. "Berfungsi di penguji XPath online tetapi tidak di Selenium" hampir selalu disebabkan oleh hal ini.

Untuk celah yang ditinggalkan oleh XPath 1.0, jawabannya biasanya adalah bahasa pemrograman yang Anda gunakan. Ekstrak data dengan XPath, lalu terapkan ekspresi reguler di Python atau JavaScript di mana Anda juga dapat memeriksa bagian mana yang cocok.

Menulis Selektor yang Tetap Berfungsi Setelah Perombakan Desain

Lembar panduan memberi tahu Anda apa saja yang mungkin dilakukan; bagian ini membahas opsi mana yang sebaiknya dipilih, karena perbedaan antara selektor yang bertahan setahun dan selektor yang akan rusak pada Selasa depan sepenuhnya bergantung pada apa yang Anda jadikan acuan.

Gunakan makna sebagai acuan, bukan posisi. (//table)[3]/tr[2]/td[4] mengkodekan bentuk halaman yang persis pada satu momen tertentu. Jika seseorang menambahkan tabel di atasnya, semua angka akan salah — tanpa peringatan, karena ekspresi tersebut masih cocok dengan sesuatu. //th[normalize-space()='Weight']/following-sibling::td[1] mengkodekan hubungan yang tetap berlaku meskipun urutan diubah, karena label berpindah bersama nilainya.

Pilih atribut yang stabil daripada yang dihasilkan. ID dan atribut data-* yang dipilih oleh pengembang jauh lebih tahan lama daripada nama kelas, yang berubah setiap kali seseorang mengubah gaya. Banyak kerangka kerja front-end modern menghasilkan nama kelas yang di-hash — css-1x9dj2k — yang berubah pada setiap build; mengacu pada nama-nama tersebut menjamin terjadinya kerusakan.

Periksa data terstruktur yang tertanam sebelum menulis selektor apa pun. Banyak sekali halaman yang menyertakan JSON-LD dalam blok <script type="application/ld+json">, karena hal ini mendukung fitur pencarian. Memparsing data tersebut jauh lebih stabil daripada memparsing HTML yang sudah dirender, karena dirancang untuk dibaca mesin dan tetap utuh meskipun desain visual diubah sepenuhnya. Tiga puluh detik untuk memeriksanya dapat menggantikan satu sore pemeliharaan selektor.

Pastikan bentuk data yang Anda ekstrak. Inilah kebiasaan yang membedakan pipeline yang gagal secara jelas dari yang gagal secara diam-diam. Jika harga harus sesuai dengan pola mata uang, periksalah. Jika halaman kategori tidak pernah memiliki kurang dari dua puluh item, jadikan jumlah kurang dari dua puluh sebagai kesalahan, bukan hasil. Selektor yang mulai mencocokkan elemen yang salah akan menghasilkan data yang masuk akal, terstruktur dengan baik, namun salah — dan tidak ada pengecualian yang dilemparkan sama sekali.

Simpan selektor di satu tempat. Tersebar di seluruh basis kode, empat puluh string XPath berarti empat puluh beban pemeliharaan terpisah. Jika dikumpulkan dalam satu modul dengan nama, mereka menjadi peta dari apa yang Anda andalkan, dan pembaruan setelah perancangan ulang hanya memakan waktu satu jam, bukan satu hari.

Dan lakukan pengujian terhadap HTML yang telah disimpan. Menyimpan salinan setiap halaman yang Anda parsing berarti bahwa ketika sebuah selektor tidak berfungsi, Anda dapat membandingkan markup lama dengan yang baru dan melihat dengan tepat apa yang berubah. Mengunduh ulang untuk melakukan debug lebih lambat, menghabiskan bandwidth, dan mungkin memberikan halaman yang berbeda dari halaman yang mengalami kegagalan.

Kapan Sebaiknya Menggunakan CSS

XPath memang lebih kuat, tetapi kurang mudah dibaca. CSS adalah pilihan default yang tepat untuk sebagian besar tugas pemilihan elemen.

Gunakan CSS jika: Anda memilih elemen berdasarkan kelas, ID, atribut, atau hubungan keturunan. div.card > p.price lebih jelas daripada sintaks XPath yang setara, didukung lebih baik oleh berbagai alat bantu, dan umumnya lebih cepat.

Gunakan XPath jika: Anda perlu mencocokkan berdasarkan konten teks, yang sama sekali tidak dapat dilakukan oleh CSS; Anda perlu menavigasi ke orang tua atau leluhur; Anda memerlukan logika posisi relatif terhadap saudara sebaris dengan cara yang tidak dapat diekspresikan oleh :nth-child; atau Anda sedang melakukan kueri terhadap XML, bukan HTML.

Perhatikan bahwa CSS telah menutup sebagian kesenjangan tersebut. :has() menyediakan seleksi bersyarat berdasarkan saudara dan keturunan di browser modern, sehingga dt:has(+ dd) kini dapat diekspresikan. Yang masih tidak dapat dilakukan oleh CSS adalah seleksi berdasarkan teks, dan pencocokan teks justru merupakan hal yang dibutuhkan oleh pola label-nilai.

Menggabungkan keduanya dalam satu basis kode adalah hal yang wajar dan masuk akal: CSS untuk 90% kasus yang sederhana, XPath untuk 10% kasus yang rumit.

Pertanyaan Lainnya

Untuk apa XPath digunakan?

Untuk menavigasi dan memilih node dalam dokumen XML dan HTML. Dalam praktiknya, XPath digunakan untuk web scraping, otomatisasi pengujian browser, serta melakukan kueri terhadap berkas konfigurasi dan data XML. XPath mampu menggambarkan hubungan — induk, saudara, konten teks — yang tidak dapat dilakukan oleh selektor CSS.

Apa perbedaan antara / dan // dalam XPath?

Tanda garis miring tunggal (/) memilih anak langsung; tanda garis miring ganda (//) memilih keturunan pada kedalaman berapa pun. //div/p cocok dengan paragraf yang induk langsungnya adalah div, sedangkan //div//p cocok dengan paragraf di mana pun di dalam div.

Mengapa XPath contains() tidak mengembalikan apa pun?

Biasanya karena Anda memberikan himpunan node. XPath mengubah himpunan node menjadi string dengan mengambil node pertama dalam urutan dokumen dan membuang sisanya, sehingga contains(//p, 'x') hanya memeriksa paragraf pertama. Gunakan //p[contains(., 'x')] sebagai gantinya.

Bagaimana cara memilih berdasarkan kelas di XPath?

Gunakan //div[contains(concat(' ', normalize-space(@class), ' '), ' name ')], yang menambahkan spasi di sekitar atribut sehingga hanya token utuh yang cocok. Sebuah contains(@class, 'btn') juga akan cocok dengan btn-primary. Jika Anda hanya memilih berdasarkan kelas, selektor CSS lebih jelas dan secara default lebih tepat.

Apakah XPath mendukung ekspresi reguler?

Tidak di XPath 1.0, yang diimplementasikan oleh browser dan Selenium. XPath 2.0 dan versi selanjutnya menambahkan matches() dan replace(), serta pustaka sisi server seperti lxml mendukung re:test() dari EXSLT. Untuk otomatisasi browser, ekstrak dengan XPath dan terapkan regex dalam bahasa pemrograman Anda.

Apa perbedaan antara //div[1] dan (//div)[1]?

//div[1] menerapkan predikat per elemen induk, memilih div pertama di bawah setiap elemen induk yang memiliki satu — atau mungkin banyak — node. (//div)[1] mengumpulkan semua div sesuai urutan dokumen dan mengambil yang pertama, yang tepatnya hanya satu node.

Apakah XPath peka huruf besar-kecil?

Ya, secara keseluruhan — nama elemen, nama atribut, dan perbandingan string. XPath 1.0 tidak memiliki fungsi lower-case(), sehingga pencocokan yang tidak peka huruf besar-kecil memerlukan translate() dengan huruf besar dan kecil yang dinyatakan secara eksplisit.

Haruskah saya menggunakan XPath atau selektor CSS?

Gunakan CSS untuk kelas, ID, atribut, dan hubungan keturunan — karena lebih jelas dan didukung dengan lebih baik. Gunakan XPath ketika Anda perlu mencocokkan konten teks, menavigasi ke leluhur, atau mengekspresikan logika posisional yang tidak dapat dilakukan oleh CSS. Menggunakan keduanya dalam satu basis kode adalah hal yang wajar.

Kesimpulan

Inti yang berguna dari XPath sebenarnya tidak banyak: // untuk mencari di mana saja, predikat dalam tanda kurung siku untuk menyaring, @ untuk atribut, beberapa fungsi string, dan sumbu saudara (sibling axes) untuk menavigasi relatif terhadap sesuatu yang dapat Anda identifikasi.

Tiga kebiasaan berikut dapat mencegah sebagian besar masalah. Bungkus perbandingan teks dengan normalize-space(), karena HTML asli ditampilkan dengan format yang rapi dan pencocokan eksak akan gagal. Gunakan contains() di dalam predikat agar dievaluasi per node, karena konversi string dari sekumpulan node secara diam-diam hanya mengambil yang pertama. Dan lebih baik gunakan teks atau pengenal sebagai acuan daripada posisi, karena struktur bisa berubah sedangkan teks biasanya tidak.

Kemudian ingatlah versi mana yang Anda tuju. Browser dan Selenium menyediakan XPath 1.0 — tanpa ekspresi reguler, tanpa lower-case(), tanpa ends-with() — dan ekspresi yang berfungsi di penguji daring mungkin tidak menggunakan salah satu dari itu dan tetap gagal karena alasan lain yang tercantum di bawah ini. Saat Anda membutuhkan fitur yang tidak ada di versi 1.0, ekstrak data menggunakan XPath dan selesaikan sisanya dalam bahasa pemrograman Anda.