Python破解携程点击文字验证

本次使用到的知识

  • Python selenium模块
  • 百度通用文字识别SDK的调用,api自己去申请,每天最多50次免费调用,文档地址:http://ai.baidu.com/docs#/OCR-API/top,用阿里和腾讯的也可以。
  • Python 类的使用
  • Python 图片二值化
  • Python base64模块
  • Python IO

 

发现问题

上一个博客写的是使用selenium爬取携程网酒店的评论信息,虽然加了一定的休眠,但是好像爬久了还是被携程发现了,等到再次想爬取时必须要先验证,先看一下是携程的验证方法吧

首先进去要做的就是先将滑块滑到最右边 

之后出现的就是这种验证

需要根据顺序点击图中的文字。

 

 分析问题

下面我们一个一个的讲怎么破解携程的反爬验证

   (1)滑动滑块

这一点相对来说破解的方法比较简单,直接使用selenium模块将滑块滑动到最右端,首先复制滑块的class名称:cpt-img-double-right-outer,然后使用selenium的find_elements_by_class_name获取到滑块元素:

scrollElement = driver.find_elements_by_class_name('cpt-img-double-right-outer')[0]

之后使用ActionChains类的click_and_hold方法按住滑块:

ActionChains(driver).click_and_hold(on_element=scrollElement).perform()

然后分为三次将滑块移动到最右端:

#第一次滑动
ActionChains(driver).move_to_element_with_offset(to_element=scrollElement, xoffset=30, yoffset=10).perform()
#第二次滑动
ActionChains(driver).move_to_element_with_offset(to_element=scrollElement, xoffset=100, yoffset=20).perform()
#第三次滑动
ActionChains(driver).move_to_element_with_offset(to_element=scrollElement, xoffset=200, yoffset=50).perform()

之后滑块验证就被破解了:

(2)按顺序点击文字

这一块相对来说是整个破解最麻烦的一步,但是也不是没有办法,首先需要分析一下人工验证的步骤:

  1. 认出上面小图中的文字
  2. 认出下面大图中的文字,并知道每个字的位置
  3. 根据上面小图中文字按顺序依次点击下面大图中的文字
  4. 点击提交按钮
  5. 验证成功

那么问题来了,使用代码怎么完成上面的步骤呢?一个一个来:

识别上面小图中的文字

下载保存小图==》图片二值化,方便识别,因为原图很乱==》调用百度通用文字识别,识别小图中的文字

识别下面大图中的文字,并获取到文字的位置

下载保存大图==》图片二值化,方便识别==》调用百度通用文字识别,识别大图中的文字,并获取到每个字的位置信息

根据上面小图中文字按顺序依次点击下面大图中的文字

根据获取到的小图中的文字+下面大图中文字的位置==》获取到待点击的文字的位置==》调用selenium点击验证

点击提交按钮

点击正确之后使用selenium点击提交按钮,识别成功,不成功则再次验证

 

代码实现

from selenium import webdriver
from selenium.webdriver import ActionChains
import time
import base64
from PIL import Image
from aip import AipOcr


# 破解携程反爬验证
class unlockScrapy(object):

    def __init__(self, driver):
        super(unlockScrapy, self).__init__()
        # selenium驱动
        self.driver = driver
        self.WAPPID = '百度文字识别appid'
        self.WAPPKEY = '百度文字识别appkey'
        self.WSECRETKEY = '百度文字识别secretkey'
        # 百度文字识别sdk客户端
        self.WCLIENT = AipOcr(self.WAPPID, self.WAPPKEY, self.WSECRETKEY)

    # 按顺序点击图片中的文字
    def clickWords(self, wordsPosInfo):
        # 获取到大图的element
        imgElement = self.driver.find_element_by_xpath(
            "/html/body/div[3]/div[3]/img")
        # 根据上图文字在下图中的顺序依次点击下图中的文字
        for info in wordsPosInfo:
            ActionChains(self.driver).move_to_element_with_offset(
                to_element=imgElement, xoffset=info['location']['left'] + 20,
                yoffset=info['location']['top'] + 20).click().perform()
            time.sleep(1)

    # 下载上面的小图和下面的大图
    def downloadImg(self):
        # 小图的src
        codeSrc = self.driver.find_element_by_xpath(
            "/html/body/div[3]/div[1]/img").get_attribute("src")
        # 大图的src
        checkSrc = self.driver.find_element_by_xpath(
            "/html/body/div[3]/div[3]/img").get_attribute("src")
        # 保存下载
        fh = open("code.jpeg", "wb")
        # 由于其src是base64编码的,因此需要以base64编码形式写入
        fh.write(base64.b64decode(codeSrc.split(',')[1]))
        fh.close()
        fh = open("checkCode.jpeg", "wb")
        fh.write(base64.b64decode(checkSrc.split(',')[1]))
        fh.close()

    # 图片二值化,便于识别其中的文字
    def chageImgLight(self):
        im = Image.open("code.jpeg")
        im1 = im.point(lambda p: p * 4)
        im1.save("code.jpeg")
        im = Image.open("checkCode.jpeg")
        im1 = im.point(lambda p: p * 4)
        im1.save("checkCode.jpeg")

    # 破解滑动
    def unlockScroll(self):
        # 滑块element
        scrollElement = self.driver.find_elements_by_class_name(
            'cpt-img-double-right-outer')[0]
        ActionChains(self.driver).click_and_hold(
            on_element=scrollElement).perform()
        ActionChains(self.driver).move_to_element_with_offset(
            to_element=scrollElement, xoffset=30, yoffset=10).perform()
        ActionChains(self.driver).move_to_element_with_offset(
            to_element=scrollElement, xoffset=100, yoffset=20).perform()
        ActionChains(self.driver).move_to_element_with_offset(
            to_element=scrollElement, xoffset=200, yoffset=50).perform()

    # 读取图片文件
    def getFile(self, filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()

    # 识别上面小图中的文字
    def iTow(self):
        try:
            op = {'language_type': 'CHN_ENG', 'detect_direction': 'true'}
            res = self.WCLIENT.basicAccurate(
                self.getFile('code.jpeg'), options=op)
            words = ''
            for item in res['words_result']:
                if item['words'].endswith('。'):
                    words = words + item['words'] + '\r\n'
                else:
                    words = words + item['words']
            return words
        except:
            return 'error'

    # 识别下面大图中文字的坐标
    def getPos(self, words):
        try:
            op = {'language_type': 'CHN_ENG', 'recognize_granularity': 'small'}
            res = self.WCLIENT.accurate(
                self.getFile('checkCode.jpeg'), options=op)
            # 所有文字的位置信息
            allPosInfo = []
            # 需要的文字的位置信息
            needPosInfo = []
            for item in res['words_result']:
                allPosInfo.extend(item['chars'])
            # 筛选出需要的文字的位置信息
            for word in words:
                for item in allPosInfo:
                    if word == item['char']:
                        needPosInfo.append(item)
            return needPosInfo
        except Exception as e:
            print(e)

    def main(self):
        # 破解滑块
        self.unlockScroll()
        time.sleep(2)
        # 下载图片
        self.downloadImg()
        time.sleep(2)
        # 图像二值化,方便识别
        self.chageImgLight()
        # 识别小图文字
        text = self.iTow()
        # 获取大图的文字位置信息
        posInfo = self.getPos(list(text))
        # 由于小图或大图文字识别可能不准确,因此这里设置识别出的文字少于4个则重新识别
        while len(posInfo) != 4 or len(text) != 4:
            # 点击重新获取图片,再次识别
            self.driver.find_elements_by_xpath(
                '/html/body/div[3]/div[4]/div/a')[0].click()
            time.sleep(2)
            self.downloadImg()
            time.sleep(2)
            text = self.iTow()
            posInfo = self.getPos(list(text))
        time.sleep(3)
        print('匹配成功,开始点击')
        # 点击下面大图中的文字
        self.clickWords(posInfo)
        # 点击提交按钮
        self.driver.find_elements_by_xpath(
            '/html/body/div[3]/div[4]/a')[0].click()
        time.sleep(2)
        # 如果破解成功,html的title会变
        if self.driver.title != '携程在手,说走就走':
            print('破解成功')
        else:
            # 再次尝试
            print('破解失败,再次破解')
            self.main()


def unlock():
    driver = webdriver.Chrome()
    # 打开Chrome浏览器,需要将Chrome的驱动放在当前文件夹
    driver.get(
        'https://hotels.ctrip.com/hotel/6278770.html#ctm_ref=hod_hp_hot_dl_n_2_7')
    # 开始破解
    unlock = unlockScrapy(driver)
    unlock.main()

if __name__ == '__main__':
    unlock()

程序执行后会打开Chrome浏览器,然后就会开始破解携程的验证,破解过程如下:

  • 12
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: Python文字点选验证是指利用Python编程语言实现的一种验证机制,通过文字点选来验证用户的身份或进行某些操作。 在实现中,可以使用Python的GUI库如Tkinter或PyQt等来创建图形用户界面,其中包含需要用户点击文字内容。用户需要按照特定的要求选择正确的文字,以完成验证。 一种常见的实现方式是使用图片文字作为验证内容,用户需要根据要求在一组选项中选择正确的项。这可以防止自动化程序进行恶意操作,保护网站等系统的安全。 实现文字点选验证的步骤如下: 1. 创建一个图形界面,包含验证内容和选项。 2. 根据需求,随机生成验证内容,并将其展示在界面上。 3. 生成选项,并将其展示在界面上,其中包含一个正确的选项和其他几个错误选项。 4. 监听用户的点击事件,当用户点击了某个选项后,进行判断是否选择正确。 5. 根据用户的选择结果,给出相应的反馈,当选择正确时,验证通过;当选择错误时,提示用户继续选择。 文字点选验证具有较高的安全性,因为用户需要主动进行选择,而不是简单的输入验证码。同时,利用Python的编程能力,可以灵活地设计验证内容和选项,提高验证的难度和安全性。 在实际应用中,文字点选验证被广泛应用于各类网站的用户注册、登录、找回密码等流程中,以及防止恶意爬虫等行为。通过结合Python的强大编程能力,可以更好地保护系统的安全和用户的隐私。 ### 回答2: Python文字点选验证是一种用于验证用户输入的机制。通常用于网站表单中的验证码功能。在这种验证中,用户需要从给定的文字选项中选择正确的一个或多个选项,以证明他们是真实的用户,并不是自动化程序或恶意机器人。 Python中实现文字点选验证可以使用各种技术和库。一种常见的方法是通过在网页中使用HTML和CSS创建一个包含文字选项的表单。然后,使用Python的Web框架(如Django或Flask)来处理表单提交和验证。 在实现中,我们可以在后端代码中定义一个包含正确选项的列表,并从中随机选择若干个选项作为验证码。然后,将这些选项通过HTML和CSS渲染到网页上,并使用JavaScript为它们添加交互性。用户需要点击正确的选项才能通过验证。 在后端,可以编写验证逻辑来判断用户选择的是否是正确的选项。如果是,则表明用户是真实的,并且可以继续进行后续操作。否则,可以提示用户重新选择,或采取其他防止恶意行为的措施。 通过Python文字点选验证,可以有效地减少自动化程序和恶意机器人对网站的干扰。同时,它也给用户带来了一定的便利性,因为只需要进行简单的选项点击即可完成验证。这种验证机制已经广泛应用于各种网站和应用中,提高了用户体验并增强了安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值