網站如何識別 你是 selenium爬蟲?那我們怎麼解決(反反爬)

我們經常會拿selenium進行自動登錄來搭建cookie池,對於不想自己網站被爬的站主/開發人員來說,防止自動化腳本操作網站自然是反爬必須要做的工作。那麼,他們究竟有哪些手段來檢測用戶是否是selenium呢?今天就來總結一下常見的識別selenium的方法以及各種解決之道。

WebDriver識別

爬蟲程序可以藉助渲染工具從動態網頁中獲取數據,“藉助”其實是通過對應的瀏覽器驅動(及Webdriver)向瀏覽器發出指令的行爲。也就是說,開發者可以根據客戶端是否包含瀏覽器驅動這一特徵來區分正常用戶和爬蟲程序。

識別的原理

網頁只要設置了檢查webdriver的Javascript方法,就很容易發現爬蟲。使用的方法就是Navigator對象的webdriver屬性,用這個屬性來判斷客戶端是否通過WebDriver驅動瀏覽器。如果監測到客戶端的webdriver屬性存在,則無法繼續操作獲取數據。selenium,Puppeteer都存在WebDriver屬性。

監測結果有3種,分別是

  • true

  • false

  • undefind。

最廣爲人知的識別是否是selenium的方法就是 window.navigator.webdriver,當瀏覽器被打開後,js就會給當前窗口一個window屬性,裏面存放着用戶的各種"信息"。

使用渲染工具有 webdriver 屬性時,navigation.webdriver的返回值時true。反之則會返回false或者undefind。

在這裏插入圖片描述
正常用戶訪問時的 webdriver 爲 undefined

在這裏插入圖片描述
selenium訪問時爲true

簡單的js來反爬 selenium

<script>
	if(window.navigator.webdriver == true){
	    document.write("<span>看到這段就代表你是爬蟲</span>")
	}else{
	    document.write("<span>真正的信息在這兒呢</span>")
	}
</script>
  1. 現在把這段代碼保存到HTML中分別正常打開和selenium打開
  • selenium打開
    在這裏插入圖片描述

  • 正常瀏覽器打開
    在這裏插入圖片描述

其實,不只是webdriver,selenium打開瀏覽器後,還會有這些特徵碼:

webdriver  
__driver_evaluate  
__webdriver_evaluate  
__selenium_evaluate  
__fxdriver_evaluate  
__driver_unwrapped  
__webdriver_unwrapped  
__selenium_unwrapped  
__fxdriver_unwrapped  
_Selenium_IDE_Recorder  
_selenium  
calledSelenium  
_WEBDRIVER_ELEM_CACHE  
ChromeDriverw  
driver-evaluate  
webdriver-evaluate  
selenium-evaluate  
webdriverCommand  
webdriver-evaluate-response  
__webdriverFunc  
__webdriver_script_fn  
__$webdriverAsyncExecutor  
__lastWatirAlert  
__lastWatirConfirm  
__lastWatirPrompt  

只要識別到這些,那麼該用戶就是selenium無誤了

WebDriver識別的繞過方法

瞭解了WebDriver識別的原理和返回值後,我們就能相處應對的辦法。既然 Web Driver 的識別依賴navigation.webdriver的返回值,那麼我們在觸發Javascript辦法前將navigation.webdriver的返回值改爲false或者undefind,問題就解決了。

script = 'Object.defineProperty(navigator,"webdriver",{get:() => false,});'

示例:

from selenium.webdriver import Chrome
import time

brower = Chrome(executable_path=r'D:\python\chromedriver_win32\chromedriver.exe')
url = 'http://www.porters.vip/features/webdriver.html'
brower.get(url)
script = 'Object.defineProperty(navigator,"webdriver",{get:() => false,});'

#運行Javascript
brower.execute_script(script)

#定位按鈕並點擊
brower.find_element_by_css_selector('.btn.btn-primary.btn-lg').click()

#定位到文章內容元素
elements = brower.find_element_by_css_selector('#content')
time.sleep(1)
print(elements.text)
brower.close()

值得一提的是,淘寶的登錄滑塊驗證頁面也是用到了這個方法,使用selenium套件操作滑塊後會出現“哎呀,出錯了,點擊刷新再來一次”這樣的提示。

注意: 這種修改該屬性值的辦法只在當前頁面有效,當瀏覽器打開新標籤或新窗口時需要重新執行改變navigator.webdriver值的JavaScript代碼。

其他的解決辦法

  1. 使用火狐瀏覽器
  • 很多時候selenium+谷歌打不開目標網站,都可以用火狐試試。

  • 因爲selenium只是一個控制瀏覽器的工具,而chromedriver和geckodriver都不是selenium官方發佈的(鬼知道誰發佈的),因此在控制瀏覽器方面會有不同的差異,具體原理不再贅述,總之很多網站不能用selenium+chrome就可以試試firefox。

(理論上IE也可能會達到相應效果,但IE內核實在太爛了,selenium+IE=龜速爬蟲)

  1. 給 webdriver 的 options增加參數
  • 谷歌瀏覽器的設置中有一個參數名爲excludeSwitches,它的值是一個數組,向裏面添加chrome的命令就可以在selenium打開chrome後自動執行數組內的指令,我們向裏面添加一個enable-automation

    from selenium import webdriver
    from selenium.webdriver import ChromeOptions
    
    option = ChromeOptions()
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    brower = webdriver.Chrome(options=option)
    brower.get('file:///C:/Users/Administrator/Desktop/js.html')
    

    此時運行這段代碼,發現可以拿到正確的信息

    在這裏插入圖片描述

  1. 中間人代理mitmproxy

mitmproxy其實和 fiddler/charles 等抓包工具的原理有些類似,作爲一個第三方,它會把自己僞裝成你的瀏覽器向服務器發起請求,服務器返回的response會經由它傳遞給你的瀏覽器,你可以通過編寫腳本來更改這些數據的傳遞,從而實現對服務器的“欺騙”和對客戶端的“欺騙”。

具體原理和使用見此

下面提供一個防屏蔽selenium的簡單demo

# my_demo.py
from mitmproxy import ctx  
    
def response(flow):  
    # 'js'字符串爲目標網站的相應js名 
    if 'js' in flow.request.url:  
        for i in ['webdriver', '__driver_evaluate', '__webdriver_evaluate', '__selenium_evaluate', '__fxdriver_evaluate', '__driver_unwrapped', '__webdriver_unwrapped', '__selenium_unwrapped', '__fxdriver_unwrapped', '_Selenium_IDE_Recorder', '_selenium', 'calledSelenium', '_WEBDRIVER_ELEM_CACHE', 'ChromeDriverw', 'driver-evaluate', 'webdriver-evaluate', 'selenium-evaluate', 'webdriverCommand', 'webdriver-evaluate-response', '__webdriverFunc', '__webdriver_script_fn', '__$webdriverAsyncExecutor', '__lastWatirAlert', '__lastWatirConfirm', '__lastWatirPrompt', '$chrome_asyncScriptInfo', '$cdc_asdjflasutopfhvcZLmcfl_']:  
            ctx.log.info('Remove %s from %s.' % (i, flow.request.url))  
            flow.response.text = flow.response.text.replace('"%s"' % (i), '"NO-SUCH-ATTR"')  
        flow.response.text = flow.response.text.replace('t.webdriver', 'false')  
        flow.response.text = flow.response.text.replace('ChromeDriver', '')

然後我們使用如下命令行啓動腳本

mitmdump.exe -S my_demo.py

然後通過selenium就可以正常訪問一些屏蔽selenium的網站了

  1. pyppeteer

它是一個基於node.js的chrome官方框架,主要用於操作谷歌無頭模式進行各種操作,pyppeteer則是puppeteer的python版本。

它的作用和selenium是類似的,通過腳本操作無頭谷歌,但是它並不會有selenium那麼多的特徵字符串,可以做到完全把“自己”當作真人操作。

當然,它還是有缺點的.雖然puppeteer一直在更新,但是pyppeteer已經停止更新將近一年了,所以無法保證它以後是否可用。同樣因爲它是基於谷歌無頭的,因此它只能用於谷歌無頭,不想selenium一樣,編寫完腳本只需改變少量代碼,便可以在多種瀏覽器中運行。

下面是一個簡單的demo

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch()
    page = await browser.newPage()
    await page.goto('file:///C:/Users/Administrator/Desktop/js.html')
    print(await page.content())

asyncio.get_event_loop().run_until_complete(main())

如果你電腦中沒有chromium,執行這段代碼後會自動幫你安裝,然後再運行這段代碼,但是非常慢,所以建議自己網上下載chromium後再執行腳本




參考原址:知乎大佬 https://blog.csdn.net/weixin_43870646/article/details/105418801

參考原址:CSDN道友 https://zhuanlan.zhihu.com/p/78368287?from_voters_page=true

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章