爬蟲簡單滑塊驗證selenium+webdriver、pyppeteer

本次筆記主要針對某企業信息查詢網站做的滑塊驗證,內容爲簡單的滑塊,主要記錄出現的幾種問題。

一、解決方案介紹

1、selenium + webdriver

        本方案爲最常用的解決方案,但是在 Google Chrome 版本 79 會遇到問題,無法抹除 webdriver 的指紋,可適當降低 Chrome 的版本來解決,還可以使用  mitmproxy 來過濾js,但是也難以解決這個問題。比較你需要先知道指紋所在的js,以及所有特徵字符串。

2、pyppeteer

        本方案可以繞過 webdriver 識別,推薦使用,但是無頭模式我沒有成功,業務也不需要無頭模式,希望有解決方案的同學可以告知一下。

 

二、selenium + webdriver

1、代碼

#coding:utf-8
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains

# 滑塊驗證
def get_track(distance):
    track = []
    current = 0
    mid = distance * 3 / 4
    t = 0.2
    v = 0
    while current < distance:
        if current < mid:
            a = 2
        else:
            a = -3
        v0 = v
        v = v0 + a * t
        move = v0 * t + 1 / 2 * a * t * t
        current += move
        track.append(round(move))
    return track

def slide_discern(company_url):
    # 滑塊驗證
    print('開啓了滑塊驗證!!!')
    chrome_options = Options()
    # 無頭模式
    # chrome_options.add_argument('--headless')
    # chrome_options.add_argument('--disable-gpu')
    chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
    driver = webdriver.Chrome(options=chrome_options)  # 獲取到需滑動的按鈕
    driver.get(company_url)
    driver.maximize_window()  # 全屏打開
    source = driver.find_element_by_xpath('//*[@id="nc_1_n1z"]')
    action = ActionChains(driver)
    # 按住左鍵不放
    action.click_and_hold(source).perform()
    # 開始滑動
    distance = 340  # 模擬以人爲速度拖動
    track = get_track(distance)
    for i in track:
        time.sleep(1)
        action.move_by_offset(xoffset=i, yoffset=0).perform()
        action.reset_actions()
    # 釋放鼠標
    action.release().perform()
    verify_btn = driver.find_element_by_xpath('//*[@id="verify"]')
    ActionChains(driver).click(verify_btn).perform()
    driver.quit()
    print('驗證結束!!')

url = '''https://www.qichacha.com/search?key={}'''.format(company_name)
slide_discern(url)  # 滑塊驗證

代碼改自 博客園-菜鳥SSS:https://www.cnblogs.com/renshaoqi/p/10956950.html

2、問題分析

1) webdriver 被識別,滑塊始終驗證不通過,如 1.1 的圖顯示

原因:使用selenium 的時候, 在開發者工具,控制檯輸出:window.navigator.webdriver 的值爲 true,而正常使用瀏覽器會呈現 undefined ,因此被識別到爬蟲的行爲,所以驗證不通過。

         

解決:網友最常使用的是添加參數,代碼如下:

from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(options=option)

注意:正如本博客開篇所講,Google Chrome 版本 79 會遇到問題,原因來自 https://ask.csdn.net/questions/1016271

三、pyppeteer

1、代碼

#coding:utf-8
import asyncio
from pyppeteer import launch

# 獲取屏幕尺寸
def screen_size():
    """使用tkinter獲取屏幕大小"""
    import tkinter
    tk = tkinter.Tk()
    width = tk.winfo_screenwidth()
    height = tk.winfo_screenheight()
    tk.quit()
    return width, height

# 滑塊移動
async def try_validation(page, distance=308):
    # 將距離拆分成兩段,模擬正常人的行爲
    distance1 = distance - 10
    distance2 = 10
    btn_position = await page.evaluate('''
       () =>{
        return {
         x: document.querySelector('#nc_1_n1z').getBoundingClientRect().x,
         y: document.querySelector('#nc_1_n1z').getBoundingClientRect().y,
         width: document.querySelector('#nc_1_n1z').getBoundingClientRect().width,
         height: document.querySelector('#nc_1_n1z').getBoundingClientRect().height
         }}
        ''')
    x = btn_position['x'] + btn_position['width'] / 2
    y = btn_position['y'] + btn_position['height'] / 2
    await page.mouse.move(x, y)
    await page.mouse.down()
    await page.mouse.move(x + distance1, y, {'steps': 30})
    await page.waitFor(800)
    await page.mouse.move(x + distance1 + distance2, y, {'steps': 20})
    await page.waitFor(800)
    await page.mouse.up()

# 主函數
async def main():
    # browser = await launch()  # 無頭模式
    browser = await launch(headless=False, args=['--disable-infobars', '--no-sandbox'])
    page = await browser.newPage()
    url = 'https://www.qichacha.com/index_verify?type=companysearch&back=/search?key=公司'
    await page.goto(url)  # 加載網頁
    # 最大化窗口
    width, height = screen_size()
    await page.setViewport({
        "width": width,
        "height": height
    })
    # 滑塊驗證,驗證按鈕點擊
    await page.waitFor(2000)
    await try_validation(page)
    normal_login = await page.xpath('//*[@id="verify"]')
    await normal_login[0].click()
    await page.waitFor(3000)
    await page.close()

# 函數調用
asyncio.get_event_loop().run_until_complete(main())

代碼改自 CSDN-程序猿王小賤:https://blog.csdn.net/qq393912540/article/details/91956136

2、問題分析

1)能繞過對 webdriver 的驗證,在控制檯可以看到

無頭模式沒有成功,業務沒有不需要無頭模式沒去嘗試,希望成功的同學能告知一下。

 

發佈了13 篇原創文章 · 獲贊 11 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章