99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁精彩閱讀Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱
Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱
2022-02-17
收藏
Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

CDA數(shù)據(jù)分析師

出品作者:CDALevel Ⅰ

持證人崗位:數(shù)據(jù)分析師

行業(yè):大數(shù)據(jù)

眾所周知,規(guī)范性的網(wǎng)絡(luò)爬蟲可以幫助Decision-maker在低成本下獲得想要的信息,不僅如此,做科研、寫論文、包括現(xiàn)在的大學(xué)生都可以利用該技術(shù)獲得相應(yīng)的數(shù)據(jù)。在數(shù)據(jù)為王的時(shí)代,網(wǎng)絡(luò)爬蟲是每個(gè)coder都需要必備的技能。然而,隨著爬蟲事業(yè)的發(fā)展,網(wǎng)站也開始部署了一些反爬蟲措施,最典型的莫過于12306等網(wǎng)站。其中,驗(yàn)證碼是常用的表單登錄反爬蟲措施。coder在編寫程序爬蟲的時(shí)候或多或少都會(huì)遇到驗(yàn)證碼的人機(jī)判別。當(dāng)然,驗(yàn)證碼不是一成不變的,隨著互聯(lián)網(wǎng)技術(shù)的發(fā)展,驗(yàn)證碼的樣式也變得越來越多。比如包括中文漢字、中文符號(hào)、英文字符的圖形驗(yàn)證碼、移動(dòng)滑塊驗(yàn)證碼、滑動(dòng)宮格驗(yàn)證碼、計(jì)算題驗(yàn)證碼、點(diǎn)觸驗(yàn)證碼等等。

本文選擇目前市場上較為流行且難度較大的移動(dòng)滑塊驗(yàn)證碼,并在介紹其樣式的基礎(chǔ)上進(jìn)一步選擇更為高級(jí)的無原圖有空隙的移動(dòng)滑塊驗(yàn)證碼,利用Python語言結(jié)合超級(jí)鷹平臺(tái)高效實(shí)現(xiàn)滑塊路徑長度的計(jì)算,并以小不點(diǎn)搜索網(wǎng)址(https://www.xiaoso.net/)作為案例作為代碼實(shí)現(xiàn),使讀者更為直觀的體驗(yàn)。

本文采用Anaconda進(jìn)行Python編譯,主要涉及的Python模塊:

  • PIL
  • chaojiying
  • time
  • selenium

本章分為三部分講解:

  1. 移動(dòng)滑塊驗(yàn)證碼樣式背景
  2. 解決原理與創(chuàng)新點(diǎn)
  3. 案例與代碼

一、移動(dòng)滑塊驗(yàn)證碼樣式背景

移動(dòng)滑塊驗(yàn)證碼目的是讓使用者將指定的部分拖動(dòng)到缺口部分,完成圖形的拼合。目前市場上主要有兩種樣式,一種是無空隙的,換句話說就是拖動(dòng)的滑塊一開始是處于左側(cè)邊緣的,如下圖所示,此類我稱之為無空隙移動(dòng)滑塊。

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

另一種則是有空隙的,也即拖動(dòng)的滑塊一開始不在左側(cè)邊緣,而是與左側(cè)邊緣存在一定距離的,最常見的就是如下圖所示的企鵝拼圖。

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

除此樣式的不同之外,更深層次的區(qū)別有無原圖與有原圖。熟悉網(wǎng)絡(luò)爬蟲技術(shù)的coder都知道,在網(wǎng)頁源代碼中是存在一個(gè)frame框架來裝驗(yàn)證碼整個(gè)驗(yàn)證程序,而在解決怎么自動(dòng)破解這個(gè)移動(dòng)滑塊驗(yàn)證碼的時(shí)候,我們需要下載驗(yàn)證碼原圖,通過一系列技術(shù)發(fā)現(xiàn)拖動(dòng)滑塊與缺口的距離(第二部分會(huì)詳解)。而這張?jiān)瓐D就是區(qū)別所在,下面為兩個(gè)定義的解釋:

無原圖驗(yàn)證碼:只有帶滑塊的圖,沒有不帶滑塊的原圖

有原圖驗(yàn)證碼:有不帶滑塊的圖

上面的注釋可能有些云里霧里,那么以無空隙移動(dòng)滑塊驗(yàn)證碼舉例,無原圖驗(yàn)證碼和有原圖驗(yàn)證碼的圖片如下:

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

二、解決原理與本文創(chuàng)新點(diǎn)

在每個(gè)網(wǎng)站進(jìn)行表單登錄,如間隔較長時(shí)間進(jìn)行微信登錄就有移動(dòng)滑塊驗(yàn)證碼的出現(xiàn),也有在對(duì)多頁進(jìn)行信息爬取的時(shí)為防止是機(jī)器操縱而彈出的移動(dòng)滑塊驗(yàn)證碼。而這些都需要我們?cè)诖a中判別是否需要進(jìn)行驗(yàn)證碼拖動(dòng)。以微信登錄為例子,由于驗(yàn)證碼在第一次登錄肯定是會(huì)彈出來的,因此,我們只需在代碼中一步一步來即可,不用加判斷條件。

而后便是移動(dòng)滑塊驗(yàn)證碼自身的解決問題。換位思考一下,如果不用機(jī)器用的是人工,那么我們會(huì)根據(jù)肉眼的信息自然而然的判斷將滑塊拖動(dòng)到缺口位置,但是機(jī)器是沒有肉眼和判斷力。因此,作為coder,應(yīng)該給予機(jī)器判別能力,能做的即是告訴機(jī)器滑塊的位置以及滑塊移動(dòng)的距離。

在第一部分講解了移動(dòng)滑塊驗(yàn)證碼有兩種類別,有空隙和無空隙的。先介紹無空隙情況下如何實(shí)現(xiàn)滑塊移動(dòng)距離的計(jì)算。

市面上常用的方式是有邊緣檢測(cè)算法,該算法是基于在移動(dòng)滑塊驗(yàn)證碼中,缺口的位置四周邊緣有明顯的斷裂痕跡。邊緣檢測(cè)算法有Canny算子、Sobel算子等進(jìn)行計(jì)算,大致過程就是將原始的移動(dòng)滑塊驗(yàn)證碼圖片進(jìn)行圖像灰度化、高斯平滑繼而識(shí)別到邊緣,整個(gè)過程可以借助Python中的opencv庫進(jìn)行。識(shí)別到邊緣后,對(duì)缺口和滑塊的輪廓面積做一個(gè)限定條件,接著計(jì)算滑塊和缺口的質(zhì)心,進(jìn)而計(jì)算所需位移。不同算子的邊緣檢測(cè)算法準(zhǔn)確度是不一樣的,普遍都較低且位移誤差大。耗時(shí)方面,由于是對(duì)圖像進(jìn)行識(shí)別,可想而知其速度是不盡人意的。對(duì)于無空隙的移動(dòng)滑塊驗(yàn)證碼的情況下,coder僅僅把缺口的質(zhì)心位置識(shí)別出來即可。而對(duì)于有空隙的情況下,就需要計(jì)算滑塊和缺口的質(zhì)心,即設(shè)定滑塊和缺口的輪廓條件,繼而計(jì)算滑塊的移動(dòng)距離。

市面上除了邊緣檢測(cè)算法外,還有一種準(zhǔn)確度較高的,也是普遍再用的方法。這種方法是將帶缺口的移動(dòng)滑塊驗(yàn)證碼和不到缺口的移動(dòng)滑塊驗(yàn)證碼進(jìn)行RGB像素做差。設(shè)定一個(gè)閾值并遍歷兩張圖片中的RGB像素,如果相同地方上的差值小于這個(gè)閾值那么認(rèn)為圖像基本是 一致的,反之則是不一致,可以認(rèn)為是缺口。找到這個(gè)缺口后,對(duì)于無空隙的驗(yàn)證碼圖片來說將缺口的質(zhì)心橫坐標(biāo)計(jì)算出來即是滑動(dòng)的距離。而對(duì)于有空隙的驗(yàn)證碼圖片來說,就需要有原圖移動(dòng)滑塊驗(yàn)證碼圖片和不帶缺口的移動(dòng)滑塊驗(yàn)證碼圖片,這樣滑塊和缺口的位置才能通過RGB像素對(duì)比得到出來。然而,在大多網(wǎng)頁上是不存在有原圖移動(dòng)滑塊驗(yàn)證碼圖片的,需要通過一系列設(shè)置才能夠得到,這將在第三部分案例中詳細(xì)講到。這個(gè)方法可以明顯感覺到準(zhǔn)確度是比較大的,但是要求也是比較苛刻,需要有原圖移動(dòng)滑塊驗(yàn)證碼圖片。

下面從公式角度理解滑塊移動(dòng)距離的計(jì)算,首先是無空隙的移動(dòng)滑塊驗(yàn)證碼,如下圖

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

可以看到,當(dāng)coder求出滑塊的質(zhì)心坐標(biāo)$C{s}$和缺口的質(zhì)心坐標(biāo)$C{g}$后,直接用橫坐標(biāo)$C{g1}-C{s1}$相減即可。要計(jì)算的滑塊移動(dòng)距離$d$即為$d=C{g1}-C{s1}$,上面講解過其實(shí)無空隙的移動(dòng)滑塊驗(yàn)證碼在編程中可以偷懶,因?yàn)榘雮€(gè)滑塊的長度有時(shí)在某些網(wǎng)頁中是被允許接受的,也即直接計(jì)算缺口的質(zhì)心$C_{s}$作為移動(dòng)距離$d$也是可以的。

接著講解有空隙的移動(dòng)滑塊驗(yàn)證碼的情況,如下圖:

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

有空隙的情況就可能復(fù)雜點(diǎn),coder直接利用$d=C{g1}-C{s1}$公式得到滑塊的計(jì)算距離是最快的。而如果想要像無空隙移動(dòng)滑塊驗(yàn)證碼一樣偷懶的話是不行的,如上圖直接計(jì)算質(zhì)心$C{g}$的橫坐標(biāo)外,還需要減上空隙的距離、滑塊的一半長度,即$d = C{g1}-d{g}-d{m}$。

  • 創(chuàng)新點(diǎn)
  • 因此,本文在滑塊的移動(dòng)距離計(jì)算方面創(chuàng)新性的提出一種高效且準(zhǔn)確度極高的一種方法,借助驗(yàn)證碼識(shí)別平臺(tái)---超級(jí)鷹。它的技術(shù)就是使用目前AI領(lǐng)域最為流行的深度學(xué)習(xí)進(jìn)行驗(yàn)證碼識(shí)別。超級(jí)鷹提供多種編程語言的調(diào)用API,當(dāng)然就包括本文需要的Python編程語言。下載地址為https://www.chaojiying.com/download/Chaojiying_Python.rar。除此之外,使用者需要在該平臺(tái)上注冊(cè)賬號(hào)。注冊(cè)賬號(hào)之后方能調(diào)用API。超級(jí)鷹可以對(duì)多種類別的驗(yàn)證碼進(jìn)行識(shí)別,如數(shù)字圖像驗(yàn)證碼、中文漢字圖像驗(yàn)證碼、純英文驗(yàn)證碼、不定長漢字英文數(shù)字等,本文需要用到的移動(dòng)滑塊驗(yàn)證碼同樣也有。在編程程序中,我們只需在相應(yīng)的位置上寫上對(duì)應(yīng)的驗(yàn)證碼類型即可。
  • 利用該方法,可以對(duì)移動(dòng)滑塊驗(yàn)證碼進(jìn)行一刀切解決,不用考慮是否有無原圖、有原圖這種情況。如果是采用有空隙的移動(dòng)滑塊驗(yàn)證碼圖片,那么就會(huì)返回滑塊和缺口的坐標(biāo)$C{s}$和$C{g}$,coder繼而在利用橫坐標(biāo)相減即可。
  • 這種方式不僅在耗時(shí)上得到成倍的縮減,并且準(zhǔn)確度也是極高的。

三、案例與代碼

在了解了無原圖、有原圖、無空隙、有空隙相關(guān)特征的滑塊驗(yàn)證碼后,本文選擇無原圖有空隙的滑塊驗(yàn)證碼作為案例,選擇小不點(diǎn)搜索網(wǎng)站(https://www.xiaoso.net/)為案例網(wǎng)站,進(jìn)去以后如下圖所示:

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

該網(wǎng)站是一個(gè)類似于百度、搜狗的這種搜索引擎。它的特點(diǎn)在于,他主要是視頻結(jié)果呈現(xiàn),給出一句關(guān)鍵詞后,會(huì)給出在知名視頻平臺(tái)(B站、youku、qq等)上有關(guān)該關(guān)鍵詞的視頻。因此,小不點(diǎn)對(duì)于經(jīng)常找相關(guān)視頻材料的小伙伴們也是一個(gè)大的福利,可以節(jié)省下不少的時(shí)間。

進(jìn)去以后,可以看到右上角有個(gè)登錄頁面,點(diǎn)進(jìn)去后呈現(xiàn)如下頁面

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

由于我們是第一次進(jìn)入,也即是新用戶,因此,直接進(jìn)行新用戶注冊(cè)即可,無需掃碼,填寫手機(jī)號(hào)等信息。注冊(cè)之后,讀者們可以嘗試登錄,在輸入完用戶名和密碼后會(huì)彈出一個(gè)驗(yàn)證碼,該驗(yàn)證碼就是本文重點(diǎn)講的無原圖有空隙移動(dòng)滑塊驗(yàn)證碼。我們需要用Python編程實(shí)現(xiàn)自動(dòng)登錄(自動(dòng)表單登錄)

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

Tips:有讀者會(huì)問實(shí)現(xiàn)這個(gè)小不點(diǎn)自動(dòng)登錄有什么用呢?本文可以給出答案:這個(gè)小不點(diǎn)網(wǎng)站僅在本文做一個(gè)例子體現(xiàn),讓讀者可以清洗明了如何使用Python實(shí)現(xiàn)自動(dòng)登錄。在往后實(shí)現(xiàn)QQ郵箱自動(dòng)登錄、爬蟲時(shí)遇到反爬蟲就可以舉一反三。

接下來將講解如何在Python中實(shí)現(xiàn)小不點(diǎn)網(wǎng)站的自動(dòng)登錄。

首先,我們需要明確下思路,我們做這個(gè)的自動(dòng)登錄的流程圖應(yīng)如下所示:

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱
  • 登錄頁面解析

其實(shí)整個(gè)登錄頁面是很比較簡潔的,我們讓機(jī)器實(shí)現(xiàn)自動(dòng)輸入英文用戶名、密碼、點(diǎn)擊提交即可。整個(gè)過程只有三步,那如何讓機(jī)器找到填寫與點(diǎn)擊的位置呢,我們就需要找到網(wǎng)頁的源代碼,在源代碼中找到三個(gè)元素對(duì)應(yīng)的相關(guān)代碼即可。

如何打開網(wǎng)頁源代碼?在所在頁面按F12即可,然后同時(shí)按住ctrl+shift+C即可快捷的進(jìn)入到鼠標(biāo)拖動(dòng)模式,該模式下利用鼠標(biāo)點(diǎn)擊即可到達(dá)相應(yīng)位置的源代碼,比如點(diǎn)擊"英文用戶名",效果如圖下所示

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱

可以看到"英文用戶名"元素的類名為input,是一個(gè)輸入文本類型,那么如何取出其代碼呢?其實(shí)這里所說的代碼只是籠統(tǒng)的概念,本質(zhì)上是讓機(jī)器識(shí)別出元素的位置。那么識(shí)別元素的位置在網(wǎng)頁中有許多方式,例如利用id去導(dǎo)航,class類去導(dǎo)航、css等。本文則主要選擇xpath去導(dǎo)航,xpath可以理解為機(jī)器(Python中的selenium工具)使用路徑表達(dá)式在 XML 文檔中進(jìn)行導(dǎo)航。除此之外,本文還少量用到name屬性,如上面那張圖,name=“username”在該網(wǎng)頁中是有且只有一個(gè)的,那么就可以直接同name進(jìn)行導(dǎo)航。

具體怎么得到這些元素的相關(guān)屬性實(shí)現(xiàn)導(dǎo)航呢,很簡單,在右側(cè)對(duì)應(yīng)代碼中鼠標(biāo)右鍵點(diǎn)擊,找到copy,選擇"copy xpath"即可。

同理,英文用戶名密碼、提交均可以使用上述方法。此外,點(diǎn)擊提交后會(huì)彈出移動(dòng)滑塊驗(yàn)證碼。這個(gè)驗(yàn)證碼在實(shí)現(xiàn)滑塊的拖動(dòng)與點(diǎn)擊依舊是上述的xpath元素定位方法。但稍有不同的是,需要先切換到驗(yàn)證碼所在frame中。frame為框,可以理解為在一個(gè)網(wǎng)頁中嵌套的頁面,frame不是獨(dú)立的頁面而是原本網(wǎng)頁中一個(gè)產(chǎn)物。因此,在編程的時(shí)候需要注意,要從原本的frame中切換到驗(yàn)證碼所在的frame,不然會(huì)報(bào)錯(cuò)。

  • Python操縱
  • 在利用Python實(shí)現(xiàn)小不點(diǎn)搜索網(wǎng)表單自動(dòng)登錄時(shí),需要用到一個(gè)非常經(jīng)典的網(wǎng)站自動(dòng)化測(cè)試庫---selenium。這個(gè)庫支持各種瀏覽器如Google、Firebox等主流頁面。不僅如此,還支持Windows、Linus等系統(tǒng)。
  • 安裝完selenium以后,就需要學(xué)習(xí)如何使用并結(jié)合"登錄頁面解析"部分實(shí)現(xiàn)元素定位。相關(guān)代碼如下:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains import time
from selenium.webdriver.support.ui import WebDriverWait
from chaojiying import Chaojiying_Client
    # 啟動(dòng)瀏覽器
    def Launch_browser(self): self.driver = webdriver.Chrome() self.wait = WebDriverWait(self.driver, 10, 0.5) self.driver.get(self.url)
        account = self.account
        pwd = self.pwd self.driver.find_element_by_name('username').send_keys(account) self.driver.find_element_by_name('password').send_keys(pwd) self.driver.find_element_by_xpath(self.enter).click()
        # 等待className為geetest_slider_button的元素在元素表中出現(xiàn)
        time.sleep(2)

這段代碼是使用類定義編寫的,首先引入相關(guān)庫。

webdriver.Chrome()這句函數(shù)是調(diào)出Google瀏覽器,比如在anaconda中的spyder編譯器,會(huì)彈出一個(gè)Google瀏覽器頁面。這相當(dāng)于完成機(jī)器自動(dòng)打開瀏覽器這一操作。接下來就是讓機(jī)器跳轉(zhuǎn)到小不點(diǎn)搜索網(wǎng)站,用的是self.driver.get(self.url)這一函數(shù)。self.url這里指的是小不點(diǎn)搜索網(wǎng)站的網(wǎng)址。

跳轉(zhuǎn)后就會(huì)到熟悉的登錄界面,在界面中如何導(dǎo)航到英文用戶名和密碼對(duì)應(yīng)的位置并輸入進(jìn)去呢?代碼中

account = self.account ##輸入小不點(diǎn)注冊(cè)的賬號(hào) pwd = self.pwd #輸入小不點(diǎn)注冊(cè)的密碼 self.driver.find_element_by_name('username').send_keys(account) # 找到賬號(hào)位置并給予信息 self.driver.find_element_by_name('password').send_keys(pwd) #找到密碼位置并給予信息 self.driver.find_element_by_xpath(self.enter).click() #模擬點(diǎn)擊提交按鈕

便是導(dǎo)航到元素對(duì)應(yīng)位置與點(diǎn)擊提交的操縱,可以看到本文使用name元素定位的,這也應(yīng)征了上一部分所說,'username'和'password'在該頁面是獨(dú)立存在。最后的代碼time.sleep(2)是防止網(wǎng)速過慢導(dǎo)致滑塊驗(yàn)證碼出現(xiàn)延遲而跟不上機(jī)器識(shí)別的節(jié)奏導(dǎo)致的問題出現(xiàn)。

接下來就是移動(dòng)滑塊驗(yàn)證碼的破解,破解當(dāng)然需要超級(jí)鷹,但是超級(jí)鷹服務(wù)的引入下一部分在說明。而破解的前提是要獲取移動(dòng)滑塊驗(yàn)證碼的圖片,這里本文將利用selenium庫中的截屏功能,將移動(dòng)滑塊驗(yàn)證碼的圖片整一張保存至本地中。代碼如下

# 移動(dòng)滑塊驗(yàn)證碼截圖 def get_picture(self): self.driver.switch_to_frame(self.frame) #一定要轉(zhuǎn)到驗(yàn)證碼的框,才能定位?。?! self.slider = self.driver.find_element_by_xpath(self.slider_xpath) ## 先將滑塊隱藏,獲取原圖,在截圖,在復(fù)原 self.driver.execute_script("document.getElementsByClassName('{}')[0].style['display'] = 'none'".format(self.gap_xpath)) self.driver.find_element_by_xpath('//*[@id="slideBgWrap"]').screenshot(self.file_path) self.driver.find_element_by_xpath(self.img_xpath).screenshot(self.file_path2) self.driver.execute_script("document.getElementsByClassName('{}')[0].style['display'] = 'block'".format(self.gap_xpath))

首先依舊采用類與對(duì)象的寫法,第一行代碼是將frame轉(zhuǎn)到移動(dòng)滑塊驗(yàn)證碼所在的框中,第二行則是通過xpath路徑導(dǎo)航到滑塊的地方。接著則是驗(yàn)證碼截圖部分重要的地方,前面講了該案例是解決無原圖有空隙的移動(dòng)滑塊驗(yàn)證碼。如果整個(gè)過程交給了超級(jí)鷹那么無原圖有空隙這兩個(gè)問題變迎刃而解。但是,如果采用市面上常用的方法呢,那么無原圖怎么解決呢?第3行到最后一行代碼就是答案。同樣是利用selenium庫的功能,首先通過多次試驗(yàn),作者發(fā)現(xiàn)在網(wǎng)頁源代碼上做特定的修改就會(huì)使驗(yàn)證碼圖像變回原來的圖像,不會(huì)帶缺口的。修改方式就是在
document.getElementsByClassName('{}')[0]
處賦予沒有缺口屬性.style['display'] = 'none'。賦予之后就會(huì)呈現(xiàn)原圖,接著利用xpath導(dǎo)航至驗(yàn)證碼原圖的位置并screenshot截圖一下即可完成移動(dòng)滑塊驗(yàn)證碼圖片的本地保存。最后復(fù)原驗(yàn)證碼圖片,在修改處改為.style['display'] = 'block',即可重新出現(xiàn)缺口。下載下來的圖片如下圖所示(tips:由于每一次登錄的驗(yàn)證碼圖片都不一致,這里展現(xiàn)實(shí)驗(yàn)時(shí)的一次。)

Python高效實(shí)現(xiàn)滑塊驗(yàn)證碼自動(dòng)操縱
  • 超級(jí)鷹服務(wù)引入

得到了驗(yàn)移動(dòng)滑塊驗(yàn)證碼圖片之后,我們需要計(jì)算滑塊到缺口的距離,這時(shí)候使用Chaojiying無疑是高效實(shí)現(xiàn)。

在超級(jí)鷹平臺(tái)上有一個(gè)名為"Chaojiying"的Python API接口,是平臺(tái)寫好并讓Python user來直接調(diào)用的,下載地址為:
https://www.chaojiying.com/download/Chaojiying_Python.rar。而在main主程序上我們只需要在同一路徑下實(shí)現(xiàn)該代碼即可

from chaojiying import Chaojiying_Client

引入該服務(wù)后,需要上傳在超級(jí)鷹平臺(tái)注冊(cè)的賬號(hào)密碼,還有需要識(shí)別的驗(yàn)證碼圖片。具體代碼如下:

# 超級(jí)鷹 def cjy(self): # 用戶中心>>軟件ID 生成一個(gè)替換 910001 self.chaojiying = Chaojiying_Client('', '', '') # chaojiying = Chaojiying_Client('超級(jí)鷹用戶名', '超級(jí)鷹密碼', '910001') # 本地圖片文件路徑 來替換 a.jpg 有時(shí)WIN系統(tǒng)須要// im = open('./img/code_picture2.png', 'rb').read() #驗(yàn)證碼圖片存放位置 # 9101 驗(yàn)證碼類型  官方網(wǎng)站>>價(jià)格體系 3.4+版 print 后要加() # 咨詢了一下滑動(dòng)驗(yàn)證碼是選擇9101 re = self.chaojiying.PostPic(im, 9101) print('兩個(gè)坐標(biāo)') print(re) # 減去一半滑塊長度 self.diff = int(re['pic_str'].split(',')[0]) self.distance = int(re['pic_str'].split('|')[1].split(',')[0]) - self.diff print(self.distance) self.im_id = re['pic_id'] print(self.im_id)

解析:首先讀者需要在Chaojiying_client這句函數(shù)里面寫上相關(guān)的用戶名、密碼和軟件ID。其次以二進(jìn)制格式讀取移動(dòng)滑塊驗(yàn)證碼圖片并使用Chaojiying內(nèi)置函數(shù)Postpic上傳至平臺(tái)。這樣平臺(tái)就會(huì)返回我們滑塊到缺口gap的坐標(biāo),我們利用兩坐標(biāo)相減即可得到路徑。注意:在得到路徑上應(yīng)該減去一半滑塊長度,在第二部分已經(jīng)講解為何減去一半滑塊長度。

在得到滑塊移動(dòng)的路徑后,更謹(jǐn)慎的我們還需要賦予滑塊一個(gè)速度,以防止網(wǎng)站發(fā)現(xiàn)是機(jī)器人操縱。具體代碼如下:

# 獲取移動(dòng)軌跡 def get_track(self): self.track = []
        mid = self.distance * 3 / 5 current = 0 t = 0.2 v = 0 while current < self.distance: if current < mid: a = 8 else: a = -12 v0 = v
            v = v0 + a * t
            move = v * t + 1 / 2 * a * t * t
            current += move self.track.append(round(move))
        print(self.track) # 模擬移動(dòng) def move(self): self.track = self.track 
        ActionChains(self.driver).click_and_hold(self.slider).perform() for x in self.track: ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
        time.sleep(2)
        ActionChains(self.driver).release().perform() self.slider.click()

第一個(gè)def類---get_track就是定義滑塊的移動(dòng)每0.2秒的移動(dòng)距離。本文定義為在移動(dòng)路徑的$frac{2}{5}$路徑之前加速度為8,即做加速直線運(yùn)動(dòng)。后半程的加速度為-12即做減速直線運(yùn)動(dòng)。結(jié)合速度公式和位移公式即可得到每一步滑塊需要走多遠(yuǎn)。

最后使用selenium庫中的懸停鼠標(biāo)工具ActionChains拖拽住滑塊,遍歷每一步的步長,講滑塊移動(dòng)到缺口位置。

  • 總代碼

可以看到上述的代碼時(shí)以類方式封裝的,因此介紹上使用者如何運(yùn)行代碼,首先是主程序main

from no_img import scratch_main
url = 'https://www.xiaoso.net/m/member/action/login'
username = '' #輸入小不點(diǎn)賬號(hào) password = '' #輸入小不點(diǎn)密碼 enter_xpath = '//*[@id="TencentCaptcha"]'
frame = 'tcaptcha_iframe'
slider_xpath = '//*[@id="tcaptcha_drag_thumb"]'
gap_xpath = 'tc-jpp-img unselectable'
img_xpath = '//*[@id="slideBgWrap"]'
process = scratch_main(url,username,password,enter_xpath,frame,slider_xpath,gap_xpath,img_xpath)
process.main()

這個(gè)需要使用者在username和password上輸入自己在小不點(diǎn)上注冊(cè)的賬號(hào)密碼,接著是no_img程序,

'''
無原圖滑塊驗(yàn)證碼案例
author:henry
''' from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
from chaojiying import Chaojiying_Client class scratch_main(): def __init__(self,url,username,password,enter_xpath,frame,slider_xpath,gap_xpath,img_xpath): self.url = url self.file_path = './img/code_picture.png' self.file_path2 = './img/code_picture2.png' self.distance = 0 self.key = 0 self.account = username self.pwd = password self.enter = enter_xpath self.frame = frame self.slider_xpath = slider_xpath self.gap_xpath = gap_xpath self.img_xpath = img_xpath # 啟動(dòng)瀏覽器 def Launch_browser(self): self.driver = webdriver.Chrome() self.wait = WebDriverWait(self.driver, 10, 0.5) self.driver.get(self.url)
        account = self.account
        pwd = self.pwd
        time.sleep(2) self.driver.find_element_by_name('username').send_keys(account) self.driver.find_element_by_name('password').send_keys(pwd) self.driver.find_element_by_xpath(self.enter).click()
        time.sleep(2) self.driver.switch_to_frame(self.frame) #一定要轉(zhuǎn)到驗(yàn)證碼的框,才能定位?。。?/span> self.slider = self.driver.find_element_by_xpath(self.slider_xpath) # 截圖 def get_picture(self): ## 先將滑塊隱藏,獲取原圖,在截圖,在復(fù)原 self.driver.find_element_by_xpath(self.img_xpath).screenshot(self.file_path2) self.driver.execute_script("document.getElementsByClassName('{}')[0].style['display'] = 'block'".format(self.gap_xpath)) # 分割截圖獲取驗(yàn)證碼圖片,由于使用超級(jí)鷹,所以直接用上面截圖驗(yàn)證碼部分即可,不用截圖缺口 def crop_picture(self):
        pass # 超級(jí)鷹 def cjy(self): # 用戶中心>>軟件ID 生成一個(gè)替換 910001 self.chaojiying = Chaojiying_Client('', '', '') # chaojiying = Chaojiying_Client('超級(jí)鷹用戶名', '超級(jí)鷹密碼', '910001') # 本地圖片文件路徑 來替換 a.jpg 有時(shí)WIN系統(tǒng)須要// im = open('./img/code_picture2.png', 'rb').read()
        re = self.chaojiying.PostPic(im, 9202)
        print('兩個(gè)坐標(biāo)')
        print(re) # print(re['pic_str']) # 減去一半滑塊長度 self.diff = int(re['pic_str'].split(',')[0]) self.distance = int(re['pic_str'].split('|')[1].split(',')[0]) - self.diff
        print(self.distance) self.im_id = re['pic_id']
        print(self.im_id) # 獲取軌跡 def get_track(self): self.track = []
        mid = self.distance * 2 / 5 current = 0 t = 0.2 v = 0 while current < self.distance: if current < mid: a = 8 else: a = -12 v0 = v
            v = v0 + a * t
            move = v * t + 1 / 2 * a * t * t
            current += move self.track.append(round(move))
        print(self.track) # 模擬移動(dòng) def move(self): self.track = self.track 
        ActionChains(self.driver).click_and_hold(self.slider).perform() for x in self.track: ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
        time.sleep(2)
        ActionChains(self.driver).release().perform() self.slider.click() def check(self):
        pass # 關(guān)閉瀏覽器 def quit(self):
        time.sleep(5) self.driver.quit() # main方法 def main(self): self.Launch_browser() self.get_picture() self.crop_picture() self.cjy() self.get_track() self.move() self.check() if __name__ == '__main__':
    ma = scratch_main()
    ma.main()

這里需要使用者在cjy類中輸入自己在超級(jí)鷹上注冊(cè)的賬號(hào)密碼和軟件ID。此外,使用者需要把main、Chaojiyingno_img三個(gè)程序放到一個(gè)相同路徑下。

數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼

若不方便掃碼,搜微信號(hào):CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說明請(qǐng)參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }