Python公开课 - 爬虫识别滑动验证码

前言

做爬虫碰到验证码是家常便饭,现在Geetest作为作为一个专业的验证码服务提供商,为不少网站提供了用户行为的验证服务。

其中常见的就是滑动验证,也就是说用户必须手动将滑块拉到对应的图片缺口上。

作为爬虫开发者碰到这类验证码,该如何处理呢,本篇将介绍的一种,通过Selenium模拟用户滑动解锁方法。

我们以得意网登录页面为例阐述

分析网页信息

得意网的极验证是登录弹框的方式出现的,当输入用户名和密码后,点击登录将弹出极验证

弹出极验证后,我们对图片元素进行分析,发现下载了三张图片,两个.webp图像文件为一个完整图和一个有缺口的图,而.png图像文件则是滑块,但是不管是完整图合适含缺口的图,都是乱序的。那么接下来,我们需要将图片还原成正常显示的。

还原并合成图片

分析图片元素的样式信息,我们可以看到图片是合成的,也就是说你只保存所有地址的图片是不行的。它是通过background-position的方法进行合成的。

获取原始图片的及位置信息:

def get_image_and_location():
    options = Options()
    options.binary_location = '/usr/bin/google-chrome'
    options.add_argument('--headless')
    options.add_argument('--disable-gpu')
    options.add_argument('--no-sandbox')
    driver = webdriver.Chrome(executable_path='./chromedriver', chrome_options=options)

    driver.implicitly_wait(5)
    driver.get("http://www.deyi.com/account.php?mod=login")

    content = driver.find_elements_by_class_name('gt_cut_bg_slice')
    cut_loc_list = []
    img_url = None
    for i in content:
        style = i.get_attribute("style")
        import re
        img_url, x, y = re.findall('url\(\"(.*)\"\); background-position: (.*)px (.*)px;', style)[0]
        cut_loc_list.append({'x':int(x), 'y': int(y)})

    import requests
    r = requests.get(img_url)
    with open('cut.webp', 'wb') as f:
         f.write(r.content)
    from PIL import Image
    im = Image.open("cut.webp")
    rgb_im = im.convert('RGB')
    rgb_im.save('cut.jpg')

    content = driver.find_elements_by_class_name('gt_cut_fullbg_slice')
    full_loc_list = []
    img_url = None
    for i in content:
        style = i.get_attribute("style")
        import re
        img_url, x, y = re.findall('url\(\"(.*)\"\); background-position: (.*)px (.*)px;', style)[0]
        full_loc_list.append({'x':int(x), 'y': int(y)})


    import requests
    r = requests.get(img_url)
    with open('full.webp', 'wb') as f:
         f.write(r.content)
    from PIL import Image
    im = Image.open("full.webp")
    rgb_im = im.convert('RGB')
    rgb_im.save('full.jpg')
    driver.quit()
    return ('cut.jpg', cut_loc_list, 'full.jpg', full_loc_list)


还原合成图片的代码如下:

def get_merge_image(filename, location_list):
    from PIL import Image as image
    im = image.open(filename)
    new_im = image.new('RGB', (260,116))
    im_list_upper=[]
    im_list_down=[]
    for location in location_list:
        if location['y']==-58:
            im_list_upper.append(im.crop((abs(location['x']),58,abs(location['x'])+10,166)))
        if location['y']==0:
            im_list_down.append(im.crop((abs(location['x']),0,abs(location['x'])+10,58)))
    x_offset = 0
    for im in im_list_upper:
        new_im.paste(im, (x_offset,0))
        x_offset += im.size[0]
    x_offset = 0
    for im in im_list_down:
        new_im.paste(im, (x_offset,58))
        x_offset += im.size[0]
    new_im.save(filename)
    return new_im

经过处理后,可以正常还原出来两张图片full.jpg, cut.jpg

计算缺口位置

在得到了两张图片后,我们需要对他们进行比较,来计算缺口的位置,以便于移动滑块到指定的位置

思路简单点来说,就是设定一个阈值,对每个像素进行比较,找到像素不同的那个点

考虑到滑块的像素为60,所以我们可以设置起始位置为60

方法代码如下:

def get_distance(image1,image2):
    left=60
    threhold=70

    for i in range(left,image1.size[0]):
        for j in range(image1.size[1]):
            rgb1=image1.load()[i,j]
            rgb2=image2.load()[i,j]
            res1=abs(rgb1[0]-rgb2[0])
            res2=abs(rgb1[1]-rgb2[1])
            res3=abs(rgb1[2]-rgb2[2])

            if not (res1 < threhold and res2 < threhold and res3 < threhold):
                return i
    return left

划重点- 核心逻辑之移动滑块算法

在获得缺口位置后,只需要移动滑块即可,但是这里极验证对轨迹数据也进行了校验,换句话说,如果轨迹模拟被识别出是程序控制的,极验证也无法通过,这种情况会出提示信息“怪兽吃了拼图 再来一次”

经过尝试,这里给出一个简单可靠的算法

slider=driver.find_element_by_class_name("gt_slider_knob")

from selenium.webdriver import ActionChains

ActionChains(driver).click_and_hold(slider).perform()

left = dis-6
while left>0:
    import random

    x = min(random.randint(20, 30), left)
    print x
    ActionChains(driver).move_by_offset(xoffset=x, yoffset=-1).perform()
    left -= x

    time.sleep(random.random() + 0.15)
ActionChains(driver).release().perform()

至此大功搞成,可以正常实现自动登录或者注册了。

总结

极验证的滑动验证具体还是需要先了解一下页面情况,具体情况具体分析。其中的难点还是滑块的拖动轨迹处理,处理不好,一切白费。

相关阅读


相关推荐
  1. 新生儿颈椎受伤的表现有哪些 - 育儿经验
  2. 重庆市三峡幼儿园 - 重庆幼儿园黄页
  3. 深圳市福田区竹香小学
  4. 湖北将发放消费券 - 武汉新鲜事
  5. 德化三中
  6. 济宁市金乡县实验小学
  7. 警方通报:武汉男子持刀至五死一伤,嫌犯已跳桥
  8. 上海市黄浦区中华路幼儿园 - 上海幼儿园黄页
  9. 一壶浊酒难入喉 - 关于兔子先生
  10. 一群二流子
  11. 武汉市黄陂区盘龙城中心幼儿园 - 武汉幼儿园黄页
  12. 给乌鸦的罚单
  13. 茂名市第十一小学
  14. 乐乐的梦
  15. 脱单!武汉的相亲角在哪你知道吗?
  16. 苋菜传奇
  17. 深圳市宝安区西乡街道富华社区丽景城晶晶幼儿园 - 深圳幼儿园黄页
  18. 东莞市第五高级中学
  19. 南平市建阳外国语学校
  20. 郑州二七区侯寨中心学校
  21. 武汉推出越王勾践剑交通卡
  22. 百名网媒总编辑登上知音号欣赏武汉夜色
  23. 石狮第三实验小学
  24. Python公开课 - 爬虫基本原理
  25. 广东省怀集县凤岗中学
  26. 高密市康成中学
  27. 武汉一女子七天被骗220万
  28. Python公开课 - 爬虫之代理
  29. Python公开课 - Python与操作系统
  30. 内蒙古呼和浩特市赛罕区内蒙古铁骑集团幼儿园 - 呼和浩特幼儿园黄页
  31. 央媒聚焦!国庆假期173.78万人次打卡大美黄陂
  32. 技术破解钉钉打卡考勤 - 苹果手机专用完整解决方案
  33. 江苏省常州市金坛市薛埠中学
  34. 黄灯
  35. 乌龟的奖牌
  36. Python基础 - 详解django.utils.dateparse
  37. 星河185幼儿园 - 廊坊幼儿园黄页
  38. 张家口市蔚县第二中学(蔚县二中)
  39. Python公开课 - 标准库Thread详解
  40. 戴项链的比赛
  41. 新城区明诚小学
  42. 黄鼠狼的建议
  43. Google Adsense禁止将ads投放到弹出式窗口
  44. 白鹭女神
  45. 福州市钱塘小学屏北分校
  46. ImageMagick将图像转换为300dpi的两种方式
  47. 乐清市七里港镇中心小学
  48. 武汉00后大二学妹拍视频月入七十万
  49. Python公开课 - Python中的保留关键字
  50. 南京市玄武高级中学梅园校区
  51. 南宁市江南区保利城幼儿园 - 南宁幼儿园黄页
  52. 江苏省南京市浦口区小红花幼儿园 - 南京幼儿园黄页
  53. 无锡北塘盛岸实验小学
  54. 奥迪客户不满加价,被武汉4S店销售群殴
  55. 海口市龙华小学
  56. 北京市朝阳区佳华安琪幼儿园(垡头西里) - 北京幼儿园黄页
  57. 育智儿童启蒙学校
  58. 易中天给英雄武汉的一首诗 - 武汉新鲜事
  59. 临川市第八小学
  60. 怪兽的传说