本次筆記主要針對某企業信息查詢網站做的滑塊驗證,內容爲簡單的滑塊,主要記錄出現的幾種問題。
一、解決方案介紹
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 的驗證,在控制檯可以看到
無頭模式沒有成功,業務沒有不需要無頭模式沒去嘗試,希望成功的同學能告知一下。