有很多朋友在開發爬蟲的過程當中喜歡使用Selenium + Chromedriver,覺得這樣就能作到不被網站的反爬蟲機制發現。javascript
先不說淘寶這種基於用戶行爲的反爬蟲策略,僅僅是一個普通的小網站,使用一行Javascript代碼,就能輕輕鬆鬆識別你是否使用了Selenium + Chromedriver模擬瀏覽器。java
咱們來看一個例子。python
使用下面這一段代碼啓動Chrome窗口:web
from selenium.webdriver import Chrome driver = Chrome()
如今,在這個窗口中打開開發者工具,並定位到Console選項卡,以下圖所示。瀏覽器
如今,在這個窗口輸入以下的js代碼並按下回車鍵:微信
window.navigator.webdriver
能夠看到,開發者工具返回了true
。以下圖所示。工具
可是,若是你打開一個普通的Chrome窗口,執行相同的命令,能夠發現這行代碼的返回值爲undefined
,以下圖所示。網站
因此,若是網站經過js代碼獲取這個參數,返回值爲undefined
說明是正常的瀏覽器,返回true
說明用的是Selenium模擬瀏覽器。一抓一個準。這裏給出一個檢測Selenium的js代碼例子:spa
webdriver = window.navigator.webdriver; if(webdriver){ console.log('你這個傻逼你覺得使用Selenium模擬瀏覽器就能夠了?') } else { console.log('正常瀏覽器') }
網站只要在頁面加載的時候運行這個js代碼,就能夠識別訪問者是否是用的Selenium模擬瀏覽器。若是是,就禁止訪問或者觸發其餘反爬蟲的機制。插件
那麼對於這種狀況,在爬蟲開發的過程當中如何防止這個參數告訴網站你在模擬瀏覽器呢?
可能有一些會js的朋友以爲能夠經過覆蓋這個參數從而隱藏本身,但實際上這個值是不能被覆蓋的:
對js更精通的朋友,可能會使用下面這一段代碼來實現:
Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});
運行效果以下圖所示:
確實修改爲功了。這種寫法就萬無一失了嗎?並非這樣的,若是此時你在模擬瀏覽器中經過點擊連接、輸入網址進入另外一個頁面,或者開啓新的窗口,你會發現,window.navigator.webdriver
又變成了true
。以下圖所示。
那麼是否是能夠在每個頁面都打開之後,再次經過webdriver執行上面的js代碼,從而實如今每一個頁面都把window.navigator.webdriver
設置爲undefined
呢?也不行。
由於當你執行:driver.get(網址)
的時候,瀏覽器會打開網站,加載頁面並運行網站自帶的js代碼。因此在你重設window.navigator.webdriver
以前,實際上網站早就已經知道你是模擬瀏覽器了。
接下來,又有朋友提出,能夠經過編寫Chrome插件來解決這個問題,讓插件裏面的js代碼在網站自帶的全部js代碼以前執行。
這樣作固然能夠,不過有更簡單的辦法,只須要設置Chromedriver的啓動參數便可解決問題。
在啓動Chromedriver以前,爲Chrome開啓實驗性功能參數excludeSwitches
,它的值爲['enable-automation']
,完整代碼以下:
from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) driver = Chrome(options=option)
此時啓動的Chrome窗口,在右上角會彈出一個提示,不用管它,不要點擊停用
按鈕。
再次在開發者工具的Console選項卡中查詢window.navigator.webdriver
,能夠發現這個值已經自動變成undefined
了。而且不管你打開新的網頁,開啓新的窗口仍是點擊連接進入其餘頁面,都不會讓它變成true
。運行效果以下圖所示。
截至2019年02月12日20:46分,本文所講的方法能夠用來登陸知乎。若是使用 Selenium 直接登陸知乎,會彈出驗證碼;先使用本文的方法再登陸知乎,可以成功假裝成真實的瀏覽器,不會彈出驗證碼。
實際上,Selenium + Webdriver能被識別的特徵不止這一個。關於如何隱藏其餘特徵,請關注個人微信公衆號。