爬虫时遇到滑动验证,基本思路是通过selenium操作浏览器,将滑动验证的原始图片和缺口图片进行对比,找出缺口位置,然后在利用selenium模拟拖动滑块,达到验证的目的。下面就以猪八戒网为例,进行操作。

一、分析

首先访问 https://account.zbj.com/login:

登陆页面主要为上图。

点击按钮(div标签,类名为 geetest_radar_tip)后,出现滑动验证码:

这个滑动验证图片并没有原始图片,直接出现的就是缺口图片。而我们要找的就是深色缺口的位置。

观察图片标签,找到   <canvas class="geetest_canvas_slice geetest_absolute" width="260" height="160"></canvas>这个标签,如果把该标签设置的display属性设置为none,则验证图则会变为下图:

拼接的小方块隐藏掉了,这张图片更容易让我们与原图比对。

然后再找到<canvas class="geetest_canvas_fullbg geetest_fade geetest_absolute" height="160" width="260" style="display: none; opacity: 1;"></canvas>这个标签,将display设置为block:

原图显示出来,我们可以将上面两张图片的滑动验证图片进行截取,比对,即可找到缺口位置。

实现过程中要注意几点:

1.selenium在加载后,不要立即寻找标签,因为如果标签没有加载完成,会找不到,这样就会抛出错误。

2.截图的大小可以跟浏览器的内显示的大小不一样,需要计算浏览器显示大小与截图大小的比例。

3.进行滑动时,要先加速后减速,如果一直匀速,会被网站识别。

二、实现

1、导入相关要用的包:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from PIL import Image
from six import BytesIO
import time
from selenium.webdriver import ActionChains

2.主函数:

if __name__ == '__main__':browser = get_url('https://account.zbj.com/login','11111111111','********')  #此函数的定义在第3点time.sleep(1)slice_img_label = browser.find_element_by_css_selector('div.geetest_slicebg') #找到滑动图片标签browser.execute_script("document.getElementsByClassName('geetest_canvas_slice')[0].style['display'] = 'none'") #将小块隐藏full_img_label = browser.find_element_by_css_selector('canvas.geetest_canvas_fullbg') #原始图片的标签position = get_position(slice_img_label) #获取滑动验证图片的位置,此函数的定义在第4点screenshot = get_screenshot(browser) # 截取整个浏览器图片,此函数的定义在第5点position_scale = get_position_scale(browser,screenshot) #获取截取图片宽高和浏览器宽高的比例,此函数的定义在第6点slice_img = get_slideimg_screenshot(screenshot,position,position_scale) #截取有缺口的滑动验证图片,此函数的定义在第7点browser.execute_script("document.getElementsByClassName('geetest_canvas_fullbg')[0].style['display'] = 'block'") #在浏览器中显示原图screenshot = get_screenshot(browser) #获取整个浏览器图片full_img = get_slideimg_screenshot(screenshot,position,position_scale) # 截取滑动验证原图browser.execute_script("document.getElementsByClassName('geetest_canvas_slice')[0].style['display'] = 'block'")  #将小块重新显示left = compare(full_img,slice_img) #将原图与有缺口图片进行比对,获得缺口的最左端的位置,此函数定义在第8点left = left / position_scale[0] #将该位置还原为浏览器中的位置
slide_btn = browser.find_element_by_css_selector('.geetest_slider_button') #获取滑动按钮track = get_track(left) #获取滑动的轨迹,此函数定义在第9点move_to_gap(browser,slide_btn,track) #进行滑动,此函数定义在第10点success = browser.find_element_by_css_selector('.geetest_success_radar_tip') #获取显示结果的标签time.sleep(2)if success.text == "验证成功":login_btn = browser.find_element_by_css_selector('button.j-login-btn') #如果验证成功,则点击登录按钮
        login_btn.click()else:print(success.text)print('失败') 

下面是主函数中用到的各个功能性函数:

3..定义访问页面的函数:

def get_url(url,user,password):browser = webdriver.Chrome()browser.get(url)browser.maximize_window()wait = WebDriverWait(browser,10)wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_radar_btn')))user_input = browser.find_element_by_id('username')pwd_input = browser.find_element_by_id('password')btn = browser.find_element_by_css_selector('.geetest_radar_btn')user_input.send_keys(user)pwd_input.send_keys(password)btn.click()time.sleep(0.5)return browser

此函数主要是用于启动Chrome,打开网页,将用户名和密码填入相应位置,并点击验证按钮。

4.获取滑动验证图片在浏览器的位置。

使用location是获取标签左上角的位置,然后再通过该标签的大小,即可算出其四个角的位置。

def get_position(img_label):location = img_label.locationsize = img_label.sizetop, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']return (left, top, right, bottom)

5.获取整个浏览器的截图。并从内存进行读取。

def get_screenshot(browser):screenshot = browser.get_screenshot_as_png()f = BytesIO()f.write(screenshot)return Image.open(f)

6.通过对比截图和浏览器宽高的大小,算出换算比例。

由于截图是有浏览器的边缘的拖拽条,所以浏览器的宽度+10px

def get_position_scale(browser,screen_shot):height = browser.execute_script('return document.documentElement.clientHeight')width = browser.execute_script('return document.documentElement.clientWidth')x_scale = screen_shot.size[0] / (width+10)y_scale = screen_shot.size[1] / (height)return (x_scale,y_scale)

7.截取有缺口的滑动图片:

def get_slideimg_screenshot(screenshot,position,scale):x_scale,y_scale = scaleposition = [position[0] * x_scale, position[1] * y_scale, position[2] * x_scale, position[3] * y_scale]  return screenshot.crop(position)

8.将原始图片和有缺口的图片进行比较:

def compare_pixel(img1,img2,x,y):pixel1 = img1.load()[x,y]pixel2 = img2.load()[x,y]threshold = 50if abs(pixel1[0]-pixel2[0])<=threshold:if abs(pixel1[1]-pixel2[1])<=threshold:if abs(pixel1[2]-pixel2[2])<=threshold:return Truereturn Falsedef compare(full_img,slice_img):left = 0for i in range(full_img.size[0]):for j in range(full_img.size[1]):if not compare_pixel(full_img,slice_img,i,j):return ireturn left

9.计算出滑动的轨迹,其实就是简单的s = 1/2*a*t*t的简单公式。这部分代码,直接用的崔庆才博主的代码:

def get_track(distance):"""根据偏移量获取移动轨迹:param distance: 偏移量:return: 移动轨迹"""# 移动轨迹track = []# 当前位移current = 0# 减速阈值mid = distance * 4 / 5# 计算间隔t = 0.2# 初速度v = 0while current < distance:if current < mid:# 加速度为正 2a = 4else:# 加速度为负 3a = -3# 初速度 v0v0 = v# 当前速度 v = v0 + atv = v0 + a * t# 移动距离 x = v0t + 1/2 * a * t^2move = v0 * t + 1 / 2 * a * t * t# 当前位移current += move# 加入轨迹
        track.append(round(move))return track

10.进行移动:

def move_to_gap(browser,slider, tracks):"""拖动滑块到缺口处:param slider: 滑块:param tracks: 轨迹:return:"""ActionChains(browser).click_and_hold(slider).perform()for x in tracks:ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform()time.sleep(0.5)ActionChains(browser).release().perform()

以上3-10是定义的功能性函数,放在前面,2是主函数,放在后面。运行即可。也可以将其写为一个类,使用时更为方便。此处,只是为实现功能,所以就没有进一步进行规范。

转载于:https://www.cnblogs.com/ohahastudy/p/11493971.html

爬虫:滑动验证解决方法及python实现相关推荐

  1. python爬虫滑动验证码_爬虫:滑动验证解决方法及python实现

    爬虫时遇到滑动验证,基本思路是通过selenium操作浏览器,将滑动验证的原始图片和缺口图片进行对比,找出缺口位置,然后在利用selenium模拟拖动滑块,达到验证的目的.下面就以猪八戒网为例,进行操 ...

  2. python爬虫中文乱码解决方法

    python爬虫中文乱码解决方法 参考文章: (1)python爬虫中文乱码解决方法 (2)https://www.cnblogs.com/surecheun/p/9694052.html 备忘一下.

  3. python爬虫 403 Forbidden 解决方法

    python爬虫 403 Forbidden 解决方法 参考文章: (1)python爬虫 403 Forbidden 解决方法 (2)https://www.cnblogs.com/tian-sun ...

  4. Android滑动冲突解决方法

    Android滑动冲突解决方法 滑动冲突 首先讲解一下什么是滑动冲突.当你需要在一个ScrollView中嵌套使用ListView或者RecyclerView的时候你会发现只有ScrollView能够 ...

  5. Win10远程桌面连接提示“需要网络级别身份验证”解决方法

    Win10远程桌面连接提示"需要网络级别身份验证"解决方法分享.我们在使用电脑的时候,可以通过远程桌面连接的方式来进行其他用户电脑的远程桌面连接.有的用户在进行远程桌面连接的时候, ...

  6. 爬虫中的那些反爬虫措施以及解决方法

     在爬虫中遇到反爬虫真的是家常便饭了,这篇博客我想结合我自己的经验将遇到过的那些问题给出来,并给出一些解决方案. 1.UserAgent   UserAgent的设置能使服务器能够识别客户使用的操作系 ...

  7. 水仙花数python代码多种方式_水仙花数的三种解决方法(Python实现)

    先来了解一下什么是水仙花数.水仙花数是这样一个三位数:它的个位数.十位数.百位数的三次方之和,等于它自身.例如,153就是一个水仙花数,因为153=1^3+5^3+3^3.470也是一个水仙花数,因为 ...

  8. PC QQ密码登录总是要图形验证解决方法

    问题:PC QQ登录总是要图形 , 说是异地问题,但已经很久都这样了. ps:我是习惯一直用密码登录的.大概这种情况持续了快一个月. 解决方法:使用手机QQ进行扫码登录一次,之后即不需要图形验证了 .

  9. Android滑动冲突解决方法(二)

    之前的一遍学习笔记主要就Android滑动冲突中,在不同方向的滑动所造成冲突进行了了解,这种冲突很容易理解,当然也很容易解决.今天,就同方向的滑动所造成的冲突进行一下了解,这里就先以垂直方向的滑动冲突 ...

最新文章

  1. iOS 中 load 和 initialize的实现顺序
  2. numpy库:常用基本
  3. Python高级特性:切片
  4. signature=52ceb41d49ce2ed43689f29f1663e802,SINGLE SIGN ON WITH MULTIPLE AUTHENTICATION FACTORS
  5. git clone 出错SSL certificate problem, verify that the CA cert is OK.
  6. 帆软报表判断传入条件是否为空,根据逗号分隔
  7. 微软全球执行副总裁沈向洋:人工智能的机遇和挑战
  8. Java RESTful Web Service实战(第2版) 2.3 传输格式
  9. oppok3如何刷机_oppok3怎么刷机
  10. 目前使用SAP的公司列表
  11. python+nodejs+vue自驾游旅游网站系统
  12. Java 正则表达式对用户名、手机号、邮箱等验证
  13. DenseNet阅读心得体会
  14. echarts pie饼图的使用(初级版包括设置百分比)
  15. 前端之路之mac PS的安装破解
  16. 利用Python实现新冠疫情数据可视化(获取疫情历史数据,制作南丁格尔玫瑰图、疫情地图、动态疫情组合图、词云)
  17. Manifest Permissions
  18. HM-SpringCloud微服务系列11.1【多级缓存的意义JVM进程缓存】
  19. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version
  20. 2021/11/16 定时器Timer和cron表达式

热门文章

  1. Oracle在Linux平台“静默”安装(二)
  2. Tech.ED 2009前瞻:认识System Center
  3. 一款不错的基于WEB技术的文件服务器
  4. css3中transition属性详解
  5. mahout 算法集
  6. golang中的recover
  7. Linux下如何让自己的程序在开机时自动启动
  8. python五十:反射
  9. Jinja2模板引擎简介
  10. thinkphp-比较标签-eq