Saya akan mempertahankan opini tidak populer tentang tag selenium SO bahwa XPath lebih disukai daripada CSS dalam jangka panjang.
Posting panjang ini memiliki dua bagian - pertama saya akan meletakkan bukti di belakang serbet perbedaan kinerja antara keduanya adalah 0,1-0,3 milidetik (ya; itu 100 mikro detik) , dan kemudian saya akan membagikan pendapat saya mengapa XPath lebih kuat.
Perbedaan kinerja
Pertama-tama mari kita tangani "gajah di dalam ruangan" - jalur x itu lebih lambat dari css.
Dengan kekuatan cpu saat ini (baca: apa pun yang diproduksi x86 sejak 2013) , bahkan pada VM browserstack / saucelabs / aws, dan pengembangan browser (baca: semua yang populer dalam 5 tahun terakhir) itu bukan masalahnya. Mesin browser telah berkembang, dukungan xpath seragam, IE tidak sesuai dengan keinginan (mudah-mudahan bagi kebanyakan dari kita) . Perbandingan di jawaban lain ini dikutip di semua tempat, tetapi sangat kontekstual - berapa banyak yang menjalankan - atau peduli - otomatisasi terhadap IE8?
Jika ada perbedaan, itu hanya dalam sepersekian milidetik .
Namun, sebagian besar kerangka kerja tingkat yang lebih tinggi menambahkan setidaknya 1ms overhead selama panggilan selenium mentah (pembungkus, penangan, penyimpanan negara, dll); senjata pilihan pribadi saya - RobotFramework - menambahkan setidaknya 2 md, yang dengan senang hati saya korbankan untuk apa yang disediakannya. Perjalanan pulang pergi jaringan dari AWS us-east-1 ke hub BrowserStack biasanya 11 milidetik .
Jadi dengan peramban jarak jauh jika ada perbedaan antara xpath dan css, itu dibayangi oleh yang lainnya, dalam urutan besarnya.
Pengukuran
Tidak banyak perbandingan publik (saya benar-benar hanya melihat yang dikutip) , jadi - inilah kasus tunggal yang kasar, tiruan dan sederhana.
Ini akan menemukan elemen dengan dua strategi X kali, dan membandingkan waktu rata-rata untuk itu.
Target - halaman arahan BrowserStack, dan tombol "Daftar"; screenshot dari html saat menulis posting ini:
Berikut kode uji (python):
from selenium import webdriver
import timeit
if __name__ == '__main__':
xpath_locator = '//div[@class="button-section col-xs-12 row"]'
css_locator = 'div.button-section.col-xs-12.row'
repetitions = 1000
driver = webdriver.Chrome()
driver.get('https://www.browserstack.com/')
css_time = timeit.timeit("driver.find_element_by_css_selector(css_locator)",
number=repetitions, globals=globals())
xpath_time = timeit.timeit('driver.find_element_by_xpath(xpath_locator)',
number=repetitions, globals=globals())
driver.quit()
print("css total time {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, css_time, (css_time/repetitions)*1000))
print("xpath total time for {} repeats: {:.2f}s, per find: {:.2f}ms".
format(repetitions, xpath_time, (xpath_time/repetitions)*1000))
Bagi mereka yang tidak terbiasa dengan Python - ini membuka halaman, dan menemukan elemennya - pertama dengan pelacak css, kemudian dengan xpath; operasi pencarian diulangi 1.000 kali. Keluarannya adalah total waktu dalam detik untuk 1.000 pengulangan, dan waktu rata-rata untuk satu penemuan dalam milidetik.
Lokasinya adalah:
- untuk xpath - "elemen div yang memiliki nilai kelas yang tepat ini, di suatu tempat di DOM";
- cssnya mirip - "elemen div dengan kelas ini, di suatu tempat di DOM".
Dengan sengaja dipilih untuk tidak disetel terlalu jauh; juga, pemilih kelas dikutip untuk css sebagai "tercepat kedua setelah id".
Lingkungan - Chrome v66.0.3359.139, chromedriver v2.38, cpu: ULV Core M-5Y10 biasanya berjalan pada 1.5GHz (ya, "pengolah kata", bahkan bukan binatang i7 biasa) .
Berikut hasilnya:
css total time 1000 repeats: 8.84s, per find: 8.84ms
xpath total time for 1000 repeats: 8.52s, per find: 8.52ms
Jelas waktu per penemuan cukup dekat; perbedaannya 0,32 milidetik . Jangan lompat "xpath lebih cepat" - terkadang ya, terkadang css.
Mari kita coba dengan set pelacak lain, sedikit lebih rumit - atribut yang memiliki substring (pendekatan umum setidaknya bagi saya, mengikuti kelas elemen ketika sebagian darinya memiliki makna fungsional) :
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
Kedua pencari lokasi secara semantik sama - "temukan elemen div yang memiliki atribut kelasnya di substring ini".
Berikut hasilnya:
css total time 1000 repeats: 8.60s, per find: 8.60ms
xpath total time for 1000 repeats: 8.75s, per find: 8.75ms
Selisih 0,15ms .
Sebagai latihan - tes yang sama seperti yang dilakukan di blog tertaut di komentar / jawaban lain - halaman tes bersifat publik, begitu juga kode pengujian .
Mereka melakukan beberapa hal dalam kode - mengklik kolom untuk mengurutkannya, lalu mendapatkan nilainya, dan memeriksa apakah urutan UI sudah benar.
Saya akan menghentikannya - cari saja, setelah semua - ini adalah tes root, bukan?
Kode yang sama seperti di atas, dengan perubahan berikut:
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
Dan inilah hasilnya:
css total time 1000 repeats: 8.24s, per find: 8.24ms
xpath total time for 1000 repeats: 8.45s, per find: 8.45ms
Selisih 0,2 milidetik.
The "Menemukan Elemen Dengan Melintasi":
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
Hasil:
css total time 1000 repeats: 9.29s, per find: 9.29ms
xpath total time for 1000 repeats: 8.79s, per find: 8.79ms
Kali ini 0,5 ms (sebaliknya, xpath menjadi "lebih cepat" di sini).
Jadi 5 tahun kemudian (mesin browser yang lebih baik) dan hanya berfokus pada kinerja pelacak (tidak ada tindakan seperti penyortiran di UI, dll), testbed yang sama - praktis tidak ada perbedaan antara CSS dan XPath.
Jadi, dari xpath dan css, manakah dari keduanya yang harus dipilih untuk performa? Jawabannya sederhana - pilih mencari berdasarkan id .
Singkat cerita, jika id dari sebuah elemen adalah unik (seperti yang seharusnya sesuai dengan spesifikasi), nilainya memainkan peran penting dalam representasi internal browser dari DOM, dan karenanya biasanya yang tercepat.
Namun, id unik dan konstan (mis. Tidak dihasilkan secara otomatis) tidak selalu tersedia, yang membawa kita ke "mengapa XPath jika ada CSS?"
Keuntungan XPath
Dengan performa di luar gambaran, mengapa menurut saya xpath lebih baik? Sederhana - keserbagunaan, dan kekuatan.
Xpath adalah bahasa yang dikembangkan untuk bekerja dengan dokumen XML; dengan demikian, ini memungkinkan konstruksi yang jauh lebih kuat daripada css.
Misalnya, navigasi ke setiap arah di pohon - temukan elemen, lalu pergi ke kakeknya dan telusuri turunannya yang memiliki properti tertentu.
Ini memungkinkan kondisi boolean tertanam - cond1 and not(cond2 or not(cond3 and cond4))
; penyeleksi tersemat - "temukan div yang memiliki turunan ini dengan atribut ini, lalu navigasikan sesuai dengannya".
XPath memungkinkan pencarian berdasarkan nilai node (teksnya) - betapapun tidak disukai praktik ini, itu berguna terutama dalam dokumen yang terstruktur dengan buruk (tidak ada atribut yang pasti untuk diinjak, seperti id dan kelas dinamis - temukan elemen dengan teksnya konten) .
Melangkah dalam css jelas lebih mudah - seseorang dapat mulai menulis penyeleksi dalam hitungan menit; tetapi setelah beberapa hari penggunaan, kekuatan dan kemungkinan xpath dengan cepat mengatasi css.
Dan murni subjektif - css yang kompleks jauh lebih sulit untuk dibaca daripada ekspresi xpath yang kompleks.
Outro;)
Akhirnya, sekali lagi sangat subjektif - mana yang harus dipilih?
IMO, tidak ada pilihan yang benar atau salah - mereka adalah solusi berbeda untuk masalah yang sama, dan apa pun yang lebih cocok untuk pekerjaan itu harus dipilih.
Menjadi "penggemar" XPath, saya tidak malu untuk menggunakan campuran keduanya dalam proyek saya - heck, terkadang jauh lebih cepat untuk hanya membuang satu CSS, jika saya tahu itu akan melakukan pekerjaan dengan baik.