Tôi sẽ giữ quan điểm không phổ biến về thẻ SO selen rằng XPath sẽ thích hợp hơn CSS về lâu dài.
Bài đăng dài này có hai phần - đầu tiên tôi sẽ đưa ra bằng chứng xác thực về hiệu suất giữa hai phần là 0,1-0,3 mili giây (vâng, đó là 100 micro giây) và sau đó tôi sẽ chia sẻ ý kiến của mình tại sao XPath mạnh hơn.
Hiệu suất khác biệt
Đầu tiên hãy giải quyết "con voi trong phòng" - xpath đó chậm hơn css.
Với sức mạnh cpu hiện tại (đọc: bất cứ thứ gì x86 được sản xuất từ năm 2013) , ngay cả trên máy ảo browserstack / saucelabs / aws và sự phát triển của các trình duyệt (đọc: tất cả các trình duyệt phổ biến trong 5 năm qua) , điều đó hầu như không xảy ra. Các công cụ của trình duyệt đã phát triển, sự hỗ trợ của xpath là đồng nhất, IE không phải là hình ảnh (hy vọng với hầu hết chúng ta) . So sánh này trong câu trả lời khác đang được trích dẫn khắp nơi, nhưng nó rất phù hợp với ngữ cảnh - có bao nhiêu người đang chạy - hoặc quan tâm đến - tự động hóa chống lại IE8?
Nếu có sự khác biệt, nó nằm trong một phần của mili giây .
Tuy nhiên, hầu hết các khung công tác cấp cao hơn đều thêm ít nhất 1ms chi phí trên lệnh gọi selen thô (trình bao bọc, trình xử lý, lưu trữ trạng thái, v.v.); vũ khí cá nhân của tôi lựa chọn - RobotFramework - thêm ít nhất 2ms, mà tôi rất vui khi hy sinh cho những gì nó cung cấp. Một vòng mạng từ AWS us-East-1 đến trung tâm của BrowserStack thường là 11 mili giây .
Vì vậy, với các trình duyệt từ xa nếu có sự khác biệt giữa xpath và css, nó sẽ bị lu mờ bởi mọi thứ khác, theo thứ tự độ lớn.
Sự đo, sự đo lường
Không có nhiều so sánh công khai (tôi thực sự chỉ thấy một câu được trích dẫn) , vì vậy - đây là một trường hợp đơn giản, giả và đơn giản.
Nó sẽ xác định vị trí của một phần tử theo hai chiến lược X lần và so sánh thời gian trung bình cho phần tử đó.
Mục tiêu - trang đích của BrowserStack và nút "Đăng ký" của nó; ảnh chụp màn hình html khi viết bài này:
Đây là mã thử nghiệm (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))
Đối với những người không quen thuộc với Python - nó sẽ mở trang và tìm phần tử - trước tiên bằng bộ định vị css, sau đó với xpath; thao tác tìm được lặp lại 1.000 lần. Đầu ra là tổng thời gian tính bằng giây cho 1.000 lần lặp lại và thời gian trung bình cho một lần tìm thấy tính bằng mili giây.
Bộ định vị là:
- for xpath - "một phần tử div có giá trị lớp chính xác này, ở đâu đó trong DOM";
- css cũng tương tự - "một phần tử div với lớp này, ở đâu đó trong DOM".
Được chọn có chủ ý để không bị điều chỉnh quá mức; ngoài ra, bộ chọn lớp được trích dẫn cho css là "nhanh thứ hai sau một id".
Môi trường - Chrome v66.0.3359.139, chromedriver v2.38, cpu: ULV Core M-5Y10 thường chạy ở tốc độ 1,5GHz (vâng, một "xử lý văn bản", thậm chí không phải là một con thú i7 thông thường) .
Đây là kết quả:
css total time 1000 repeats: 8.84s, per find: 8.84ms
xpath total time for 1000 repeats: 8.52s, per find: 8.52ms
Rõ ràng là thời gian cho mỗi lần tìm thấy khá gần nhau; sự khác biệt là 0,32 mili giây . Đừng nhảy "đường dẫn xpath nhanh hơn" - đôi khi đúng như vậy, đôi khi là css.
Hãy thử với một bộ định vị khác, phức tạp hơn một chút - một thuộc tính có chuỗi con (ít nhất là cách tiếp cận phổ biến đối với tôi, đi sau lớp của phần tử khi một phần của nó mang ý nghĩa chức năng) :
xpath_locator = '//div[contains(@class, "button-section")]'
css_locator = 'div[class~=button-section]'
Hai bộ định vị lại giống nhau về mặt ngữ nghĩa - "tìm một phần tử div có trong thuộc tính lớp của nó là chuỗi con này".
Đây là kết quả:
css total time 1000 repeats: 8.60s, per find: 8.60ms
xpath total time for 1000 repeats: 8.75s, per find: 8.75ms
Diff của 0.15ms .
Là một bài tập - bài kiểm tra tương tự như được thực hiện trong blog được liên kết trong phần nhận xét / câu trả lời khác - trang kiểm tra là công khai và mã kiểm tra cũng vậy .
Họ đang thực hiện một số việc trong mã - nhấp vào một cột để sắp xếp theo nó, sau đó nhận các giá trị và kiểm tra việc sắp xếp giao diện người dùng có đúng không.
Tôi sẽ cắt nó - chỉ cần lấy bộ định vị, sau cùng - đây là kiểm tra gốc, phải không?
Mã tương tự như trên, với những thay đổi sau trong:
css_locator = '#table2 tbody .dues'
xpath_locator = "//table[@id='table2']//tr/td[contains(@class,'dues')]"
Và đây là kết quả:
css total time 1000 repeats: 8.24s, per find: 8.24ms
xpath total time for 1000 repeats: 8.45s, per find: 8.45ms
Chênh lệch 0,2 mili giây.
"Tìm các yếu tố bằng cách đi ngang":
css_locator = '#table1 tbody tr td:nth-of-type(4)'
xpath_locator = "//table[@id='table1']//tr/td[4]"
Kết quả:
css total time 1000 repeats: 9.29s, per find: 9.29ms
xpath total time for 1000 repeats: 8.79s, per find: 8.79ms
Lần này là 0,5 ms (ngược lại, xpath hóa ra "nhanh hơn" ở đây).
Vì vậy, 5 năm sau (các công cụ trình duyệt tốt hơn) và chỉ tập trung vào hiệu suất của bộ định vị (không có các hành động như sắp xếp trong giao diện người dùng, v.v.), cùng một thử nghiệm - thực tế không có sự khác biệt giữa CSS và XPath.
Vì vậy, ngoài xpath và css, bạn nên chọn cái nào trong hai cái để đạt hiệu suất? Câu trả lời rất đơn giản - chọn định vị theo id .
Tóm lại, nếu id của một phần tử là duy nhất (vì nó được cho là theo các thông số kỹ thuật), thì giá trị của nó đóng một vai trò quan trọng trong biểu diễn nội bộ của trình duyệt đối với DOM và do đó thường là nhanh nhất.
Tuy nhiên, id duy nhất và không đổi (ví dụ không phải được tạo tự động) không phải lúc nào cũng có sẵn, điều này đưa chúng ta đến "tại sao XPath nếu có CSS?"
Ưu điểm của XPath
Với hiệu suất ngoài bức tranh, tại sao tôi nghĩ xpath tốt hơn? Đơn giản - linh hoạt và mạnh mẽ.
Xpath là một ngôn ngữ được phát triển để làm việc với các tài liệu XML; như vậy, nó cho phép các cấu trúc mạnh mẽ hơn nhiều so với css.
Ví dụ: điều hướng theo mọi hướng trong cây - tìm một phần tử, sau đó đi đến ông bà của nó và tìm kiếm phần tử con của nó có các thuộc tính nhất định.
Nó cho phép các điều kiện boolean được nhúng - cond1 and not(cond2 or not(cond3 and cond4))
; bộ chọn nhúng - "tìm một div có các con với các thuộc tính này, sau đó điều hướng theo nó".
XPath cho phép tìm kiếm dựa trên giá trị của một nút (văn bản của nó) - tuy nhiên, thực tế này rất hữu ích, nó có ích, đặc biệt là trong các tài liệu có cấu trúc không tốt (không có thuộc tính xác định để bước vào, như id động và lớp - định vị phần tử bằng văn bản của nó nội dung) .
Bước trong css chắc chắn dễ dàng hơn - người ta có thể bắt đầu viết các bộ chọn chỉ trong vài phút; nhưng sau một vài ngày sử dụng, sức mạnh và khả năng xpath đã nhanh chóng vượt qua css.
Và hoàn toàn chủ quan - một css phức tạp khó đọc hơn nhiều so với một biểu thức xpath phức tạp.
Outro;)
Cuối cùng, một lần nữa rất chủ quan - nên chọn cái nào?
IMO, không có sự lựa chọn đúng hay sai - chúng là những giải pháp khác nhau cho cùng một vấn đề và nên chọn cái nào phù hợp hơn với công việc.
Là "fan" của XPath, tôi không ngại sử dụng kết hợp cả hai trong các dự án của mình - heck, đôi khi chỉ cần ném CSS một cái sẽ nhanh hơn nhiều, nếu tôi biết nó sẽ hoạt động tốt.