前言:
在我们使用爬虫登录账号中常常会遇到各种验证码,如:图片验证码、滑块验证……
其中滑块验证码又分有缺口滑块验证码和无缺口滑块验证码,无缺口滑块验证码只需要用户使用鼠标将滑块从左侧拖动到右侧即可。程序通过记录用户拖动滑块的轨迹,这一串的轨迹数据采用模式识别的手段就可以判断出这是否是真人在操作。
滑块验证通常需要使滑块按照正常的加速度进行拖动,停靠在一个合适的位置,在使用 Selenium 时通常需要设置一个合适的滑动加速度来使自己伪装的更像人类用户而不是计算机。
那么如何使用 Selenium 模拟这一过程呢?
无缺口滑块验证码
下面通过几个例子,来展示用 Selenium 解决这个问题的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import timefrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.chrome.options import Optionsoptions = Options() options.add_argument('--start-maximized' ) def main (): browser = webdriver.Chrome(ptions=options) url = 'https://passport.ctrip.com/user/reg/home' browser.get(url) time.sleep(2 ) browser.find_elements_by_class_name('reg_agree' )[0 ].click() time.sleep(2 ) slider = browser.find_elements_by_class_name('cpt-drop-btn' )[0 ] ele = browser.find_elements_by_class_name('cpt-bg-bar' )[0 ] time.sleep(1 ) ActionChains(browser).drag_and_drop_by_offset(slider, ele.size['width' ], -slider.size['height' ]).perform() time.sleep(2 ) browser.quit() if __name__ == '__main__' : main()
无需设置合适的滑动加速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 import randomfrom time import sleepfrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.chrome.options import Optionsoptions = Options() options.add_argument('--start-maximized' ) options.add_experimental_option('excludeSwitches' , ['enable-automation' ]) options.add_argument('--disable-blink-features=AutomationControlled' ) def get_move_track (distance ): track = [] current = 0 mid = distance * (4 / 5 ) t = random.randint(2 , 3 ) / 10 v = 0 while current < distance: if current < mid: a = 10 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 main (): browser = webdriver.Chrome(options=options) url = 'https://www.qcc.com/user_login' browser.get(url) sleep(2 ) browser.find_element_by_id('normalLogin' ).click() phone = browser.find_element_by_id('nameNormal' ) phone.send_keys('xxx' ) sleep(1 ) pwd = browser.find_element_by_id('pwdNormal' ) pwd.send_keys('xxx' ) sleep(1 ) slider = browser.find_element_by_id('nc_1_n1z' ) ele = browser.find_elements_by_class_name('nc-lang-cnt' )[0 ] tracks = get_move_track(ele.size['width' ]) ActionChains(browser).click_and_hold(slider).perform() for x in tracks: ActionChains(browser).move_by_offset(xoffset=x, yoffset=0 ).perform() sleep(2 ) browser.find_elements_by_class_name('login-btn' )[0 ].click() sleep(2 ) browser.quit() if __name__ == '__main__' : main()
⚠️注意事项:需要设置合适的滑动加速度;如果发现移动滑块动作不流畅,解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 import randomfrom time import sleepfrom selenium import webdriverfrom selenium.webdriver import ActionChainsdef get_move_track (distance ): track = [] current = 0 mid = distance * (4 / 5 ) t = random.randint(2 , 3 ) / 10 v = 0 while current < distance: if current < mid: a = 10 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 main (): browser = webdriver.Firefox() url = 'https://www.lanzou.com/u' browser.get(url) browser.maximize_window() sleep(2 ) browser.execute_script('Object.defineProperties(navigator,{webdriver:{get:()=>false}})' ) username = browser.find_element_by_id('username' ) username.send_keys('xxx' ) sleep(1 ) pwd = browser.find_elements_by_class_name('pwd' )[0 ] pwd.send_keys('xxx' ) sleep(1 ) slider = browser.find_element_by_id('nc_1_n1z' ) ele = browser.find_elements_by_class_name('nc-lang-cnt' )[0 ] tracks = get_move_track(ele.size['width' ]) ActionChains(browser).click_and_hold(slider).perform() for x in tracks: ActionChains(browser).move_by_offset(xoffset=x, yoffset=0 ).perform() sleep(2 ) browser.find_element_by_id('s3' ).click() sleep(3 ) browser.quit() if __name__ == '__main__' : main()
需要设置合适的滑动加速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import timeimport randomfrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.chrome.options import Optionsoptions = Options() options.add_argument('--start-maximized' ) options.add_experimental_option('excludeSwitches' , ['enable-automation' ]) options.add_argument('--disable-blink-features=AutomationControlled' ) def move_slider (browser ): slider = browser.find_element_by_id('nc_1_n1z' ) ele = browser.find_elements_by_class_name('nc-lang-cnt' )[0 ] time.sleep(1 ) ActionChains(browser).drag_and_drop_by_offset(slider, ele.size['width' ], -slider.size['height' ]).perform() time.sleep(1 ) def main (): browser = webdriver.Chrome(options=options) url = 'https://reg.taobao.com/member/reg/fill_mobile.htm' browser.get(url) time.sleep(2 ) browser.find_element_by_id('J_AgreementBtn' ).click() phone = browser.find_element_by_id('J_Mobile' ) phone.send_keys('xxxx' ) move_slider(browser) browser.find_element_by_id('J_BtnMobileForm' ).click() time.sleep(3 ) browser.quit() if __name__ == '__main__' : main()
注意:不要设置合适的滑动加速度,否则会失败!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 import randomfrom time import sleepfrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.chrome.options import Optionsoption = Options() option.add_argument('--start-maximized' ) option.add_argument('--disable-blink-features=AutomationControlled' ) option.add_experimental_option( 'excludeSwitches' , ['enable-automation' , 'enable-logging' ]) def get_move_track (distance ): track = [] current = 0 mid = distance * (3 / 5 ) t = random.randint(2 , 3 ) / 10 v = 0 while current < distance: if current < mid: a = 10 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 move_slider (browser ): browser.switch_to.frame(browser.find_element_by_id('baxia-dialog-content' )) slider = browser.find_element_by_id('nc_1_n1z' ) ele = browser.find_elements_by_class_name('nc-lang-cnt' )[0 ] tracks = get_move_track(ele.size['width' ]) sleep(1 ) print ('*' * 60 ) print (slider.size['width' ]) print (slider.size['height' ]) print ('*' * 60 ) ActionChains(browser).click_and_hold(slider).perform() for x in tracks: ActionChains(browser).move_by_offset(xoffset=x, yoffset=0 ).perform() def main (): browser = webdriver.Chrome(options=option) url = 'https://www.taobao.com/' browser.get(url) sleep(1 ) browser.find_elements_by_class_name('h' )[0 ].click() sleep(1 ) browser.find_element_by_id('fm-login-id' ).send_keys('username' ) sleep(0.5 ) browser.find_element_by_id( 'fm-login-password' ).send_keys('password' ) sleep(0.5 ) browser.find_elements_by_class_name( 'fm-submit' )[0 ].click() sleep(0.5 ) move_slider(browser) sleep(5 ) browser.quit() if __name__ == '__main__' : main()
需要修改chromedriver.exe
Chrome79版本以需要添加selenium参数1 options.add_argument('--disable-blink-features=AutomationControlled' )
滑块加速度设置与否都可以
注意事项
如果发现移动滑块动作不流畅,可以修改 Selenium 源码,路径如下:
1 C:\Programs\Python\Python36\Lib\site-packages\selenium\webdriver\common\actions\pointer_input.py
将其中的 DEFAULT_MOVE_DURATION = 250
的值修改到 50 左右,参考链接 ,如图:
开启 Chorme 开发者模式,关闭自动测试状态
1 options.add_experimental_option('excludeSwitches' , ['enable-automation' ])
加上这个代码会关闭 “Chrome 正受到自动测试软件的控制” 的显示
使用 Selenium 时会被部分网站监测到,这时你在 Selenium 打开的浏览器下的按 F12 进入检查,然后在 Console 下输入 window.navigator.webdriver 会发现结果为 true
,如图:
但是当你人为的打开浏览器时,同样的输入 window.navigator.webdriver 这时会发现结果为 undefined
或者 false
,如图:
这时就需要增加一个配置参数,修改 Selenium 标识,绕过网站对 Selenium 的检测
1 options.add_argument('--disable-blink-features=AutomationControlled' )
如果以上 3 点还不行的话,可以尝试修改 chromedriver 中的变量 ,注意修改后的字符串长度不能变
参考链接
淘宝爬虫之自动登录
淘宝爬虫之登陆验证(二)
使用 Python Selenium 实现拖拽动作时动作不流畅
Chome 88如何正确隐藏 webdriver?
修改 chromedriver 中的变量 $cdc_...
,注意修改后的字符串长度不能变