Python + Seleniumは、人間の行動をシミュレートするために、極端なテストスライダーの検証コードを解読します〜

前に書く:

実際、このプログラムにはまだまだ改善の余地があり、後で改善される予定です。ご容赦ください。

概要概要

  1. 画像全体のピクセルをスライダーのない画像と比較して、スライダーの位置を決定します

  2. 場所を決定するためのエッジ検出アルゴリズム

  3. 検出を避け、人間の行動をシミュレートし、スライダーをスライドさせます

成し遂げる

-これは、検証コードのスライドの効果を示すためにネットをブラッシングする例です。

#!/ usr / bin / env python 
#-*-コーディング:utf-8-*- 
#@ Time:2021/1/2 18:34 
#@ Author:huni 
#@ File:验证码2.py 
#@ Software :PyCharm 
from selenium import webdriver 
import time 
import base64 
from PIL import Image 
from io import BytesIO 
from selenium.webdriver.support.ui import WebDriverWait 
import random 
import copy 

class VeriImageUtil():

    def __init __(self):
        self.defaultConfig = { 
            "grayOffset ":20、
            "不透明 ":1、
            " minVerticalLineCount ":30 
        } 
        self.config = copy.deepcopy(self.defaultConfig)

    def updateConfig(self、config):
        #temp = copy.deepcopy(config)
        for k in self.config:
            if k in config.keys():
                self.config [k] = config [k] 

    def getMaxOffset(self、* args):
        #最大オフセット平均を計算します
        av = sum(args)/ len(args)

        maxOffset = 0 
        for a in args:
            offset = abs(av-a)
            if offset> maxOffset:
                maxOffset = offset 
        return maxOffset 

    def isGrayPx(self 、r、g、b):
        #それがグレースケールピクセルポイントであり、オフセットが変動できるかどうか
        return self.getMaxOffset(r、g、b)<self.config ["grayOffset"] 

    def isDarkStyle(self、r、 g、b):
        #灰暗风格
        return r <128およびg <128およびb <128 

    def isOpaque(self、px):
        #不透明
        return px [3]> = 255 * self.config ["opaque"] 

    def getVerticalLineOffsetX(self、bgImage):
        #bgImage = Image.open( "./ image / bg.png")
        #bgImage.im.mode = 'RGBA' 
        bgBytes = bgImage.load()

        x = 0 
        while x <bgImage.size [0]:
            y = 0 
            #点》》線、不透明度線条MaximumverticalLineCount 
            = 0 

            while y <bgImage.size [1]:
                px = bgBytes [x、y] 
                r = px [0] 
                g = px [1] 
                b = px [2] 
                #alph = px [3]
                #print 
                (px)if self.isDarkStyle(r、g、b)and self.isGrayPx(r、g、b)and self.isOpaque(px):
                    verticalLineCount + = 1 
                else:
                    verticalLineCount = 0 
                    y + = 1
                    続行

                if verticalLineCount> = self.config ["minVerticalLineCount"]:
                    #連続するピクセルはグレースケールピクセル、直線であり、スライドする必要があると考えています#print 
                    (x、y)
                    return x 

                y + = 1 

            x + = 1 
        pass 

class DragUtil():
    def __init __(self、driver):
        self.driver = driver 

    def __getRadomPauseScondes(self):
        "" " 
        :return:ランダムドラッグ一時停止時間
        " "" 
        return random.uniform(0.6、0.9)

    def SimulateDragX(self、source、targetOffsetX):
        "" "
        人を模倣するドラッグアクション:X軸に沿ってすばやくドラッグし(エラーがあります)、一時停止してからエラーを修正し
        て、ロボットとして検出されないようにします。「画像がモンスターに食べられました」などの検証エラー
        :param source:drag Html element 
        :param targetOffsetX:ドラッグターゲットのx軸距離
        :return:なし
        "" " 
        action_chains = webdriver.ActionChains(self.driver)
        #クリックしてドラッグする準備ができました
        action_chains.click_and_hold(source)
        #ドラッグ数、2〜3回
        dragCount =ランダム。デート(2、3)
        if dragCount == 2: 
            #合計エラー値
            sumOffsetx = random.randint(-15、15)
            action_chains.move_by_offset(targetOffsetX + sumOffsetx、0)
            #しばらく一時停止
            action_chains.pause(self .__ getRadomPauseScondes())
            #エラーを修正して検出されないようにするロボットとして、画像はモンスターに食べられ、検証は失敗します
            。action_chains.move_by_offset(-sumOffsetx、0)
        elif dragCount == 3:
            #合計エラー値
            sumOffsetx = random.randint(
            -15、15 action_chains.move_by_offset( targetOffsetX + sumOffsetx、0)
            #しばらく一時停止
            action_chains.pause(self .__ getRadomPauseScondes())

            #修正されたエラーの
            合計fixedOffsetX = 0 
            #最初にエラーが修正されたとき
            sumOffsetx <0の場合:
                offsetx = random.randint(sumOffsetx、0)
            else:
                offsetx = random.randint(0、sumOffsetx)

            fixedOffsetX = fixedOffsetX + offsetx 
            action_chains.move_by_offset(-offsetx、0)
            action_chains.pause(self .__ getRadomPauseScondes() )

            #最後の修正エラー
            action_chains.move_by_offset(-sumOffsetx + fixedOffsetX、0)
            action_chains.pause(self .__ getRadomPauseScondes())

        else:
            raise Exception( "システムに問題がありますか?!")

        #action_chains.drag_and_drop_by_offset( ) 
        action_chains.release()
        action_chains .perform()

    def simpleSimulateDragX(self、source、targetOffsetX):
        "" "
        人間のドラッグを模倣する単純なドラッグ:X軸に沿ってすばやくドラッグして、1つのステップで正しい位置に到達し、しばらく一時停止してから、ドラッグアクションを放します。
        ステーションBは人間と機械を区別するための一時停止時間があるかどうかに基づいて、このメソッドを適用できます。
        :param source 
        :: param targetOffsetX 
        :: return:None 
        "" " 

        action_chains = webdriver.ActionChains(self.driver)
        #クリックして準備するドラッグ
        action_chains.click_and_hold(source)
        action_chains.pause(0.2)
        action_chains.move_by_offset(targetOffsetX、0)
        action_chains.pause(0.6)
        action_chains.release()
        action_chains.perform()
 
DEF checkVeriImage(ドライバ):
    WebDriverWait(driver、5).until( 
    #スライダーは左から5ピクセル離れています
        ラムダドライバー:driver.find_element_by_css_selector( '。geetest_canvas_bg.geetest_absolute'))
    time.sleep(1)
    im_info = driver.execute_script(
        'return document.getElementsByClassName( "geetest_canvas_bg geetest_absolute")[0] .png geetest_ab png; ')
    #base64でエンコードされた画像情報を取得
    im_base64 = im_info.split('、 ')[1] 
    #バイトに
    変換タイプim_bytes = base64.b64decode(im_base64)
    with open(' ./ temp_bg.png '、' wb ' )as f:
        #画像をローカルに保存します
        f.write(im_bytes)

    image_data = BytesIO(im_bytes)
    bgImage = Image.open(image_data)
    offsetX = VeriImageUtil()。getVerticalLineOffsetX(bgImage)
    print( "offsetX:{} "。format(offsetX))
    type(offsetX)== intの場合:
        #計算
        できません、driver.find_element_by_css_selector( "。geetest_refresh_1")。click()
        checkVeriImage(driver)
        return 
    elif offsetX == 0:
        #計算できません、リロードします
        driver。find_element_by_css_selector( "。geetest_refresh_1")。click()
        checkVeriImage(driver)
        return 
    else:
        dragVeriImage(driver、offsetX)


def dragVeriImage(driver、offsetX):
    #右端が検出される可能性があります
    #ドラッグ
    eleDrag = driver.find_element_by_css_selector( "。geetest_slider_button")
    dragUtil = DragUtil(driver)
    dragUtil.simulateDragX(eleDrag、offsetX-10)
    time.sleep(2.5)

    if isNeedCheckVeriImage(driver):
        checkVeriImage(driver)
        return 
    dragUtil.simulateDragX(eleDrag、offsetX-6)

    time.sleep(2.5)
    if isNeedCheckVeriImage(driver):
        checkVeriImage (ドライバー)
        return 
    #滑块宽度40
    対称dragUtil.simulateDragX(eleDrag、offsetX-56)

    time.sleep(2.5)
    if isNeedCheckVeriImage(driver):
        checkVeriImage(driver)
        return 
    dragUtil.simulateDragX(eleDrag、offsetX-52)

    if isNeedCheckVeriImage(ドライバー):
        checkVeriImage(ドライバー)
        リターン


isNeedCheckVeriImage(ドライバ)DEF:
    。driver.find_element_by_css_selector( "geetest_panel_error")場合をis_displayed():
        ドライバ。 find_element_by_css_selector( "。geetest_panel_error_content")。click(); 
        return True 
    return False 


def task():
    #この手順は非常に重要です
    。Chromeを開発者モードに設定して、Seleniumの使用が主要なWebサイトで認識されないようにします。#options = webdriver.ChromeOptions()
    #options .add_experimental_option( 'excludeSwitches'、['enable-automation'])



    #driver = webdriver.Firefox(executable_path = r "../../../res/webdriver/geckodriver_x64_0.26.0.exe"、options = options)
    driver = webdriver.Chrome()

    driver.get( 'https://www.ieqq.net/?cid=222&tid=5584')
    time.sleep(3)

    #driver.find_element_by_xpath( '// * [@ id = " gt -register-mobile "] / div / div [2] / div [1] / div [2] / div / div [2] / div [' 
    #'1] / input ')。send_keys( "17633935269")
    #driver.find_element_by_xpath( '// * [@ id = "gt-register-mobile"] / div / div [2] / div [1] / div [2] / div / div [2] / div [2] / div [' 
    #' 1] / div ')
    。click ()#driver.find_element_by_css_selector( "。btn.btn-login")。click()
    #time.sleep(2)

    #検索バーのラベルの位置
    search_input = driver。 find_element_by_xpath( '// * [@ id = "inputvalue"]')
    time.sleep(3)
    #タグの相互作用
    search_input.send_keys( 'xxxxxx')
    #一連のjsプログラムを実行
    driver.execute_script( 'window.scrollTo(0 、document.body.scrollHeight) ')
    time.sleep(2)

    #検索ボタンの場所
    btn = driver.find_element_by_xpath(' // * [@ id = "submit_buy"] ') 

    #検索ボタンをクリックします
    btn.click()
 
    timeを。 sleep(6)
    driver.find_element_by_xpath( '// * [@ id = "captcha"] / div [3] / div [3] ') 

    。click( ) time.sleep(3) 
    checkVeriImage(driver)

    pass 


#このメソッドは確認に使用されます要素存在するかどうか、存在する場合はflag = trueを返し、そうでない場合はfalseを返します
def isElementExist(driver、css):
    try:
        driver.find_element_by_css_selector(css)
        return True
    ただし:
        return False 


if __name__ == '__ main __':
    task( )

後ろに書く

検証コード割れがある程度ログインクローラの問題を解決することができますが、
認識率は100%の認識に達することができない。したがって、ログインすることが推奨される
進むことができクローラプログラムに。あなたがシミュレートログインにクッキーを使用してすることができます
のみ初めてログインする必要があります。ログイン確認コードを手動で識別するか、QRコードをスキャンすることで、一定期間使用できます。
もちろん、それぞれに長所と短所があります。Cookieも一定期間後に無効になります。これと検証コードは異なる意見の操作です。

確認コードの詳細については、https://blog.csdn.net/weixin_43881394/article/details/108360729を参照してください。

追記

最近、多くの友人がプライベートメッセージを通じてPythonの学習問題について相談しました。コミュニケーションを促進するには、青をクリックしてディスカッションに参加し、自分でリソースベースに回答してください

 

おすすめ

転載: blog.csdn.net/weixin_43881394/article/details/112174891