反屏蔽
現在很多網站都加上了對 Selenium 的檢測,來防止一些爬蟲的惡意爬取。即如果檢測到有人在使用 Selenium 打開瀏覽器,那就直接屏蔽。
其大多數情況下,檢測基本原理是檢測當前瀏覽器窗口下的 window.navigator 對象是否包含 webdriver 這個屬性。因為在正常使用瀏覽器的情況下,這個屬性是 undefined,然而一旦我們使用了 Selenium,Selenium 會給 window.navigator 設置 webdriver 屬性。很多網站就通過 JavaScript 判斷如果 webdriver 屬性存在,那就直接屏蔽。
這邊有一個典型的案例網站:
這個網站就是使用了上述原理實現了 WebDriver 的檢測,如果使用 Selenium 直接爬取的話,那就會返回如下頁面:
這時候我們可能想到直接使用 JavaScript 直接把這個 webdriver 屬性置空,比如通過調用 execute_script 方法來執行如下代碼:
Object.defineProperty(navigator, "webdriver", {get: () => undefined})
這行 JavaScript 的確是可以把 webdriver 屬性置空,但是 execute_script 調用這行 JavaScript 語句實際上是在頁面加載完畢之后才執行的,執行太晚了,網站早在最初頁面渲染之前就已經對 webdriver 屬性進行了檢測,所以用上述方法並不能達到效果。
在 Selenium 中,我們可以使用 CDP(即 Chrome Devtools-Protocol,Chrome 開發工具協議)來解決這個問題,通過 CDP 我們可以實現在每個頁面剛加載的時候執行 JavaScript 代碼,執行的 CDP 方法叫作 Page.addScriptToEvaluateOnNewDocument,然后傳入上文的 JavaScript 代碼即可,這樣我們就可以在每次頁面加載之前將 webdriver 屬性置空了。另外我們還可以加入幾個選項來隱藏 WebDriver 提示條和自動化擴展信息,代碼實現如下:
from selenium import webdriver from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) option.add_experimental_option('useAutomationExtension', False) browser = webdriver.Chrome(options=option) browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})' }) browser.get('https://antispider1.scrape.cuiqingcai.com/')
這樣整個頁面就能被加載出來了:
對於大多數的情況,以上的方法均可以實現 Selenium 反屏蔽。但對於一些特殊的網站,如果其有更多的 WebDriver 特征檢測,可能需要具體排查。
---原文來源於崔慶才
Selenium無法點擊元素,報錯:ElementClickInterceptedException:element click intercepted
我們在進行selenium UI自動化測試時,可能會遇到元素可以定位到,但不可點擊的情況,如下錯誤:
這個問題有兩種解決方式:
方式一:
element = driver.find_element_by_xpath("表達式") driver.execute_script("arguments[0].click();", element)
方式二:
element = driver.find_element_by_xpath('表達式') webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()
這兩種方式都可以解決此問題(我采用的第一種,畢竟簡潔嘛)