python爬蟲(chóng)之驗(yàn)證碼篇3-滑動(dòng)驗(yàn)證碼識(shí)別技術(shù)
滑動(dòng)驗(yàn)證碼介紹
本篇涉及到的驗(yàn)證碼為滑動(dòng)驗(yàn)證碼,不同于極驗(yàn)證,本驗(yàn)證碼難度略低,需要的將滑塊拖動(dòng)到矩形區(qū)域右側(cè)即可完成。

這類驗(yàn)證碼不常見(jiàn)了,官方介紹地址為:https://promotion.aliyun.com/ntms/act/captchaIntroAndDemo.html
使用起來(lái)肯定是非常安全的了,不是很好通過(guò)機(jī)器檢測(cè)
如何判斷驗(yàn)證碼類型
這個(gè)驗(yàn)證碼的標(biāo)識(shí)一般比較明顯,在頁(yè)面源碼中一般存在一個(gè) nc.js 基本可以判定是阿里云的驗(yàn)證碼了
<script type="text/javascript" src="http://g.alicdn.com/sd/ncpc/nc.js?t=1552906749855"></script>
識(shí)別套路
截止到2019年3月18日,本驗(yàn)證碼加入了大量的selenium關(guān)鍵字驗(yàn)證,所以單純的模擬拖拽被反爬的概率滿高的,你也知道一般情況爬蟲(chóng)具備時(shí)效性 不確保這種手段過(guò)一段時(shí)間還可以使用!
導(dǎo)入selenium必備的一些模塊與方法 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait # from selenium.webdriver.support import expected_conditions as EC # from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from selenium.webdriver import ActionChains import time import random
在啟動(dòng)selenium之前必須要設(shè)置一個(gè)本機(jī)的代理,進(jìn)行基本的反[反爬] 處理,很多爬蟲(chóng)在獲取用戶指紋的時(shí)候,都比較喜歡selenium,因?yàn)槭褂胹elenium模擬瀏覽器進(jìn)行數(shù)據(jù)抓取,能夠繞過(guò)客戶JS加密,繞過(guò)爬蟲(chóng)檢測(cè),繞過(guò)簽名機(jī)制
但是selenium越來(lái)越多的被各種網(wǎng)站進(jìn)行了相關(guān)屏蔽,因?yàn)閟elenium在運(yùn)行的時(shí)候會(huì)暴露出一些預(yù)定義的Javascript變量(特征字符串),例如"window.navigator.webdriver",在非selenium環(huán)境下其值為undefined,而在selenium環(huán)境下,其值為true

下圖所示為selenium驅(qū)動(dòng)下Chrome控制臺(tái)打印出的值

細(xì)致的繞過(guò)去的方法,可能需要單獨(dú)的一篇博客進(jìn)行贅述了,這里我只對(duì)上面的參數(shù)進(jìn)行屏蔽,使用到的是之前博客中涉及的mitmdump進(jìn)行代理
https://docs.mitmproxy.org/stable/concepts-certificates/
mitmdump進(jìn)行代理
技術(shù)參考來(lái)源:https://zhuanlan.zhihu.com/p/43581988
關(guān)于這個(gè)模塊的基本使用,參考我前面的博客即可,這里核心使用了如下代碼
indject_js_proxy.py
from mitmproxy import ctx
injected_javascript = '''
// overwrite the `languages` property to use a custom getter
Object.defineProperty(navigator, "languages", {
get: function() {
return ["zh-CN","zh","zh-TW","en-US","en"];
}
});
// Overwrite the `plugins` property to use a custom getter.
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5],
});
// Pass the Webdriver test
Object.defineProperty(navigator, 'webdriver', {
get: () => false,
});
// Pass the Chrome Test.
// We can mock this in as much depth as we need for the test.
window.navigator.chrome = {
runtime: {},
// etc.
};
// Pass the Permissions Test.
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
'''
def response(flow):
# Only process 200 responses of HTML content.
if not flow.response.status_code == 200:
return
# Inject a script tag containing the JavaScript.
html = flow.response.text
html = html.replace('<head>', '<head><script>%s</script>' % injected_javascript)
flow.response.text = str(html)
ctx.log.info('>>>> js代碼插入成功 <<<<')
# 只要url鏈接以target開(kāi)頭,則將網(wǎng)頁(yè)內(nèi)容替換為目前網(wǎng)址
# target = 'https://target-url.com'
# if flow.url.startswith(target):
# flow.response.text = flow.url
上述腳本放置任意目錄,之后進(jìn)行mitmdump的啟動(dòng)即可
C:\user>mitmdump -s indject_js_proxy.py
Loading script indject_js_proxy.py
Proxy server listening at http://*:8080
啟動(dòng)之后,通過(guò)webdriver訪問(wèn)
測(cè)試網(wǎng)站:https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html
如果webDriver是綠色,也說(shuō)明代理起作用了

selenium爬取
接下來(lái)就是通過(guò)selenium進(jìn)行一些模擬行為的操作了,這部分代碼比較簡(jiǎn)單,編寫(xiě)的時(shí)候參考一下注釋即可。
# 實(shí)例化一個(gè)啟動(dòng)參數(shù)對(duì)象
chrome_options = Options()
# 添加啟動(dòng)參數(shù)
chrome_options.add_argument('--proxy-server=127.0.0.1:8080')
# 將參數(shù)對(duì)象傳入Chrome,則啟動(dòng)了一個(gè)設(shè)置了窗口大小的Chrome
driver = webdriver.Chrome(chrome_options=chrome_options)
關(guān)鍵函數(shù)
def move_to_gap(tracks):
driver.get("https://passport.zcool.com.cn/regPhone.do?appId=1006&cback=https://my.zcool.com.cn/focus/activity")
# 找到滑塊span
need_move_span = driver.find_element_by_xpath('//*[@id="nc_1_n1t"]/span')
# 模擬按住鼠標(biāo)左鍵
ActionChains(driver).click_and_hold(need_move_span).perform()
for x in tracks: # 模擬人的拖動(dòng)軌跡
print(x)
ActionChains(driver).move_by_offset(xoffset=x,yoffset=random.randint(1,3)).perform()
time.sleep(1)
ActionChains(driver).release().perform() # 釋放左鍵
注意看到上述代碼中有何核心的點(diǎn) --- 拖拽距離的 列表tracks
if __name__ == '__main__': move_to_gap(get_track(295))
這個(gè)地方可以借鑒網(wǎng)上的方案即可
def get_track(distance):
'''
拿到移動(dòng)軌跡,模仿人的滑動(dòng)行為,先勻加速后勻減速
勻變速運(yùn)動(dòng)基本公式:
①v=v0+at
②s=v0t+(1/2)at²
③v²-v0²=2as
:param distance: 需要移動(dòng)的距離
:return: 存放每0.2秒移動(dòng)的距離
'''
# 初速度
v=0
# 單位時(shí)間為0.2s來(lái)統(tǒng)計(jì)軌跡,軌跡即0.2內(nèi)的位移
t=0.1
# 位移/軌跡列表,列表內(nèi)的一個(gè)元素代表0.2s的位移
tracks=[]
# 當(dāng)前的位移
current=0
# 到達(dá)mid值開(kāi)始減速
mid=distance * 4/5
distance += 10 # 先滑過(guò)一點(diǎn),最后再反著滑動(dòng)回來(lái)
while current < distance:
if current < mid:
# 加速度越小,單位時(shí)間的位移越小,模擬的軌跡就越多越詳細(xì)
a = 2 # 加速運(yùn)動(dòng)
else:
a = -3 # 減速運(yùn)動(dòng)
# 初速度
v0 = v
# 0.2秒時(shí)間內(nèi)的位移
s = v0*t+0.5*a*(t**2)
# 當(dāng)前的位置
current += s
# 添加到軌跡列表
tracks.append(round(s))
# 速度已經(jīng)達(dá)到v,該速度作為下次的初速度
v= v0+a*t
# 反著滑動(dòng)到大概準(zhǔn)確位置
for i in range(3):
tracks.append(-2)
for i in range(4):
tracks.append(-1)
return tracks
代碼注釋已經(jīng)添加好,可以自行查閱,臨摹一下即可明白
最后開(kāi)始進(jìn)行嘗試,實(shí)測(cè)中,發(fā)現(xiàn)可以自動(dòng)拖動(dòng),但是,出現(xiàn)一個(gè)問(wèn)題是最后被識(shí)別為機(jī)器,這個(gè)地方,我進(jìn)行了多次的修改與調(diào)整,最終從代碼層面發(fā)現(xiàn)實(shí)現(xiàn)確實(shí)有些復(fù)雜,所以改變策略,找一下chromedriver.exe是否有修改過(guò)的版本,中間去除了selenium的一些關(guān)鍵字,運(yùn)氣不錯(cuò),被我找到了。

目前只有windows10版本和linux16.04版本
gitee地址:https://gitee.com/bobozhangyx/java-crawler/tree/master/file/%E7%BC%96%E8%AF%91%E5%90%8E%E7%9A%84chromedriver
下載之后,替換你的 chromedriver.exe

再次運(yùn)行,成功驗(yàn)證

總結(jié)
以上所述是小編給大家介紹的python爬蟲(chóng)之驗(yàn)證碼篇3-滑動(dòng)驗(yàn)證碼識(shí)別技術(shù),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
Python繪圖并標(biāo)記出指定點(diǎn)(最大值點(diǎn))方法實(shí)例
我們?cè)谟胮ython畫(huà)散點(diǎn)圖的時(shí)候經(jīng)常會(huì)需要標(biāo)記出特定的點(diǎn),這篇文章主要給大家介紹了關(guān)于Python繪圖并標(biāo)記出指定點(diǎn)(最大值點(diǎn))的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05
一步步教你用python給女朋友寫(xiě)個(gè)微信自動(dòng)提醒的程序
如今微信已成為我們?nèi)粘I畹闹饕涣鞴ぞ?但是微信自身的功能有時(shí)候可能并不能滿足我們的需要,因此我們會(huì)想是否可以進(jìn)行微信功能的拓展呢,這篇文章主要給大家介紹了關(guān)于利用python給女朋友寫(xiě)了個(gè)微信自動(dòng)提醒程序的相關(guān)資料,需要的朋友可以參考下2021-10-10
ROS1?rosbag的詳細(xì)使用并且使用python合并bag包的方法
這篇文章主要介紹了ROS1?rosbag的詳細(xì)使用,并且使用python來(lái)合并bag包,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
python中關(guān)于property的最詳細(xì)使用方法
這篇文章主要介紹了python中關(guān)于property的最詳細(xì)使用方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
python文件讀取read及readlines兩種方法使用詳解
這篇文章主要為大家介紹了python文件讀取read及readlines兩種方法的使用示例及區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Python接口測(cè)試之如何使用requests發(fā)起請(qǐng)求
這篇文章主要介紹了Python接口測(cè)試之如何使用requests發(fā)起請(qǐng)求問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Python命令行定時(shí)任務(wù)自動(dòng)化工作流程
本文介紹如何使用Python編寫(xiě)定時(shí)任務(wù),以自動(dòng)執(zhí)行命令行任務(wù)。您將學(xué)習(xí)如何安排定期的任務(wù),處理任務(wù)結(jié)果,以及如何使用Python自動(dòng)化工作流程,從而提高工作效率。無(wú)需手動(dòng)執(zhí)行重復(fù)任務(wù),Python幫您搞定2023-04-04

