一行js程式碼識別Selenium+Webdriver及其應對方案
有不少朋友在開發爬蟲的過程中喜歡使用Selenium + Chromedriver,以為這樣就能做到不被網站的反爬蟲機制發現。
先不說淘寶這種基於使用者行為的反爬蟲策略,僅僅是一個普通的小網站,使用一行Javascript程式碼,就能輕輕鬆鬆識別你是否使用了Selenium + Chromedriver模擬瀏覽器。
我們來看一個例子。
使用下面這一段程式碼啟動Chrome視窗:
from selenium.webdriver import Chrome
driver = Chrome()
現在,在這個視窗中開啟開發者工具,並定位到Console選項卡,如下圖所示。
現在,在這個視窗輸入如下的js程式碼並按下Enter鍵:
window.navigator.webdriver
可以看到,開發者工具返回了true
。如下圖所示。
但是,如果你開啟一個普通的Chrome視窗,執行相同的命令,可以發現這行程式碼的返回值為undefined
,如下圖所示。
所以,如果網站通過js程式碼獲取這個引數,返回值為undefined
說明是正常的瀏覽器,返回true
說明用的是Selenium模擬瀏覽器。一抓一個準。這裡給出一個檢測Selenium的js程式碼例子:
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 年 2 月 12 日 20:46 分,本文所講的方法可以用來登入知乎。如果使用 Selenium 直接登入知乎,會彈出驗證碼;先使用本文的方法再登入知乎,能夠成功偽裝成真實的瀏覽器,不會彈出驗證碼。
實際上,Selenium + Webdriver能被識別的特徵不止這一個。關於如何隱藏其他特徵,請關注我的微信公眾號。
相關文章
- 文字識別解決方案-OCR識別應用場景解析
- linux-HA 中heartbeat 的pg啟動指令碼的bug 及其應對方案。Linux指令碼
- Python技巧-只用一行程式碼輕鬆實現圖片文字識別Python行程
- http響應程式碼及其代表的含義HTTP
- 7個殺手級的JS一行程式碼JS行程
- 構建基於 Node.js 的條形碼識別程式Node.js
- YOLOV5 模型和程式碼修改——針對小目標識別YOLO模型
- Swift一行程式碼封裝帶有巢狀結構的json(HandyJSON的基本應用)Swift行程封裝巢狀JSON
- 常見python資料型別及其相對應的函式Python資料型別函式
- 一行 Python 程式碼Python
- js程式碼規範常用解決方案JS
- js程式碼不生效的解決方案JS
- js選項卡不會寫?JQuery一行程式碼搞定!JSjQuery行程
- 網頁惡意程式碼六大危害及其解決方案網頁
- 初識SAP解決方案及其上雲優勢
- 初識sa-token,一行程式碼搞定登入授權!行程
- 演算法識別(一)--TEA及其魔改演算法
- 目標識別程式碼解讀整理
- Emacs自動識別檔案程式碼Mac
- js使用waterfall橫向載入瀑布流,一行程式碼完成JS行程
- 一行js彈窗程式碼就能設計漂亮的彈窗廣告JS
- 一行程式碼建立cell行程
- 一行 CSS 程式碼的魅力CSS
- 一行神奇的javascript程式碼JavaScript
- 碼教授教你大資料時代的應對方案大資料
- App 黑白化實現探索,有一行程式碼實現的方案嗎?APP行程
- 程式錯誤型別及其處理型別
- NPM酷庫040:jschardet,識別資料編碼NPMJS
- 編寫可測試的Javascript程式碼(1):反模式及其解決方案JavaScript模式
- 9路棋盤識別-程式碼備份
- Web應用程式指紋識別工具BlindElephantWeb
- 奧巴馬的第一行程式碼行程
- 設計模式及其在spring中的應用(含程式碼)設計模式Spring
- HTML特殊符號及其編碼對照表HTML符號
- java基礎學習之二:變數、基本資料型別及其對應的包裝型別Java變數資料型別
- 多模態人物識別技術及其在愛奇藝視訊場景中的應用
- Java 超程式設計及其應用Java程式設計
- FindBugs Security JSP 無法識別 jsp 頁面<script>jstl</script>程式碼中的 xss 漏洞問題JS