Python3 爬虫学习笔记 C14【验证码对抗系列 — 点触验证码】


Python3 爬虫学习笔记第十四章 —— 【验证码对抗系列 — 点触验证码】

文章目录

  • 【14.1】关于点触验证码
  • 【14.2】点触验证码攻克思路
  • 【14.3】模拟登录 12306 — 总体思路
  • 【14.4】主函数
  • 【14.5】初始化函数
  • 【14.6】破解入口函数
  • 【14.7】账号密码输入函数
  • 【14.8】页面截图函数
  • 【14.9】验证码元素查找函数
  • 【14.10】获取验证码坐标函数
  • 【14.11】验证码剪裁函数
  • 【14.12】验证码坐标解析函数
  • 【14.13】验证码模拟点击函数
  • 【14.14】模拟点击登陆函数
  • 【14.15】效果实现动图
  • 【14.16】完整代码


【14.1】关于点触验证码

点触验证码是由杭州微触科技有限公司研发的新一代的互联网验证码,使用点击的形式完成验证,采用专利的印刷算法以及加密算法,保证每次请求到的验证图具有极高的安全性,常见的点触验证码如下:
01


【14.2】点触验证码攻克思路

点触验证码相对其他类型验证码比较复杂,如果依靠 OCR 图像识别点触验证码,则识别难度非常大,此时就要用到互联网的验证码服务平台,这些服务平台全部都是人工在线识别,准确率非常高,原理就是先将验证码图片提交给平台,平台会返回识别结果在图片中的坐标位置,然后我们再解析坐标模拟点击即可,常见的打码平台有超级鹰、云打码等,打码平台是收费的,拿超级鹰来说,1元 = 1000题分,识别一次验证码将花费一定的题分,不同类型验证码需要的题分不同,验证码越复杂所需题分越高,比如 7 位中文汉字需要 70 题分,常见 4 ~ 6 位英文数字只要 10 题分,其他打码平台价格也都差不多

以下以超级鹰打码平台和中国铁路12306官网来做练习


【14.3】模拟登录 12306 — 总体思路

首先在超级鹰打码平台注册账号并申请一个软件 ID,官网:http://www.chaojiying.com/ ,先充值一块钱得到 1000 题分,观察 12306 官网,发现验证码是要我们点击所有满足条件的图片,一般有 1~4 张图片满足要求,由此可确定在超级鹰打码平台的验证码类型为 9004(坐标多选,返回1~4个坐标,如:x1,y1|x2,y2|x3,y3), 获取其 Python API:http://www.chaojiying.com/download/Chaojiying_Python.rar ,然后用 Selenium 模拟登陆,获取到验证码,并将验证码发送给超级鹰后台,返回识别图片的坐标,最后模拟点击即可,整个过程的实现由主程序 12306.py 和超级鹰 API chaojiying.py 组成

整个程序包含的函数:

def __init__(): 初始化 WebDriver、Chaojiying 对象等
def crack(): 破解入口、获取、识别验证码、模拟登录
def open(): 账号密码输入
def get_screenshot(): 整个页面截图
def get_touclick_element(): 获取验证码位置
def get_position(): 获取验证码坐标
def get_touclick_image(): 剪裁验证码部分
def get_points(self, captcha_result): 分析超级鹰返回的坐标
def touch_click_words(self, locations): 模拟点击符合要求的图片
def login(self): 点击登陆按钮,完成模拟登录

整个程序用到的库:

import time
from io import BytesIO
from PIL import Image
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from chaojiying import Chaojiying
from selenium.common.exceptions import TimeoutException

【14.4】主函数

if __name__ == '__main__':crack = CrackTouClick()crack.crack()

【14.5】初始化函数

USERNAME = '155********'
PASSWORD = '***********'CHAOJIYING_USERNAME = '*******'
CHAOJIYING_PASSWORD = '*******'
CHAOJIYING_SOFT_ID = '********'
CHAOJIYING_KIND = '9004'class CrackTouClick():def __init__(self):self.url = 'https://kyfw.12306.cn/otn/resources/login.html'path = r'F:\PycharmProjects\Python3爬虫\chromedriver.exe'chrome_options = Options()chrome_options.add_argument('--start-maximized')self.browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options)self.wait = WebDriverWait(self.browser, 20)self.email = USERNAMEself.password = PASSWORDself.chaojiying = Chaojiying_Client(CHAOJIYING_USERNAME, CHAOJIYING_PASSWORD, CHAOJIYING_SOFT_ID)

定义 12306 账号(USERNAME)、密码(PASSWORD)、超级鹰用户名(CHAOJIYING_USERNAME)、超级鹰登录密码(CHAOJIYING_PASSWORD)、超级鹰软件 ID(CHAOJIYING_SOFT_ID)、验证码类型(CHAOJIYING_KIND),登录链接 url:https://kyfw.12306.cn/otn/resources/login.html ,谷歌浏览器驱动的目录(path),浏览器启动参数,并将相关参数传递给超级鹰 API


【14.6】破解入口函数

    def crack(self):self.open()image = self.get_touclick_image()bytes_array = BytesIO()image.save(bytes_array, format='PNG')result = self.chaojiying.PostPic(bytes_array.getvalue(), CHAOJIYING_KIND)print(result)locations = self.get_points(result)self.touch_click_words(locations)self.login()try:success = self.wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '.welcome-name'), '用户姓名'))print(success)cc = self.browser.find_element(By.CSS_SELECTOR, '.welcome-name')print(cc.text)except TimeoutException:self.chaojiying.ReportError(result['pic_id'])self.crack()

调用 open() 函数输入账号密码

调用 get_touclick_image() 函数获取验证码图片

利用超级鹰 Python API PostPic() 方法即可把图片发送给超级鹰后台,发送的图像是字节流格式,返回的结果是一个 JSON,如果识别成功,典型的返回结果类似于:{'err_no': 0, 'err_str': 'OK', 'pic_id': '6002001380949200001', 'pic_str': '132,127|56,77', 'md5': '1f8e1d4bef8b11484cb1f1f34299865b'},其中,pic_str 就是识别的文字的坐标,是以字符串形式返回的,每个坐标都以 | 分隔

调用 get_points() 函数解析超级鹰识别结果

调用 touch_click_words() 函数对符合要求的图片进行点击,然后点击登陆按钮模拟登陆

使用 try-except 语句判断是否出现了用户信息,判断依据是是否有用户姓名的出现,出现的姓名和实际姓名一致则登录成功,如果失败了就重试,超级鹰会返回该分值


【14.7】账号密码输入函数

    def open(self):self.browser.get(self.url)login = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.login-hd-account')))login.click()time.sleep(3)username = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#J-userName')))password = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#J-password')))username.send_keys(self.email)password.send_keys(self.password)

分析页面可知,登陆页面 URL 为:https://kyfw.12306.cn/otn/resources/login.html ,该页面默认出现的是扫描二维码登陆,所以要先点击账号登录,找到该 CSS 元素为 login-hd-account,调用 click() 方法实现模拟点击,此时出现账号密码输入框,同样找到其 ID 分别为 J-userNameJ-password,调用 send_keys() 方法输入账号密码


【14.8】页面截图函数

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

对整个页面进行截图


【14.9】验证码元素查找函数

    def get_touclick_element(self):element = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.login-pwd-code')))return element

同样分析页面,验证码所在位置的 CSS 为 login-pwd-code


【14.10】获取验证码坐标函数

    def get_position(self):element = self.get_touclick_element()time.sleep(3)location = element.locationsize = element.sizetop, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']return (top, bottom, left, right)

location 属性可以返回该图片对象在浏览器中的位置,坐标轴是以屏幕左上角为原点,x 轴向右递增,y 轴向下递增,size 属性可以返回该图片对象的高度和宽度,由此可以得到验证码的位置信息


【14.11】验证码剪裁函数

    def get_touclick_image(self, name='12306.png'):top, bottom, left, right = self.get_position()screenshot = self.get_screenshot()captcha = screenshot.crop((left, top, right, bottom))captcha.save(name)return captcha

根据验证码的坐标信息,对页面截图进行剪裁,得到验证码部分,将其保存为 12306.png


【14.12】验证码坐标解析函数

    def get_points(self, captcha_result):groups = captcha_result.get('pic_str').split('|')locations = [[int(number) for number in group.split(',')] for group in groups]return locations

get_points() 方法将超级鹰的验证码识别结果变成列表的形式


【14.13】验证码模拟点击函数

    def touch_click_words(self, locations):for location in locations:print(location)ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(), location[0]/1.25, location[1]/1.25).click().perform()

touch_click_words() 方法通过调用 move_to_element_with_offset() 方法依次传入解析后的坐标,点击即可


【14.14】模拟点击登陆函数

    def login(self):submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'J-login')))submit.click()

分析页面,找到登陆按钮的 ID 为 J-login,调用 click() 方法模拟点击按钮实现登录


【14.15】效果实现动图

最终实现效果图:(关键信息已经过打码处理)
02


【14.16】完整代码

12306.py

import time
from io import BytesIO
from PIL import Image
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from chaojiying import Chaojiying_Client
from selenium.common.exceptions import TimeoutExceptionUSERNAME = '155********'
PASSWORD = '***********'CHAOJIYING_USERNAME = '***********'
CHAOJIYING_PASSWORD = '***********'
CHAOJIYING_SOFT_ID = '******'
CHAOJIYING_KIND = '9004'class CrackTouClick():def __init__(self):     #登陆self.url = 'https://kyfw.12306.cn/otn/resources/login.html'path = r'F:\PycharmProjects\Python3爬虫\chromedriver.exe'chrome_options = Options()chrome_options.add_argument('--start-maximized')self.browser = webdriver.Chrome(executable_path=path, chrome_options=chrome_options)self.wait = WebDriverWait(self.browser, 20)self.email = USERNAMEself.password = PASSWORDself.chaojiying = Chaojiying_Client(CHAOJIYING_USERNAME, CHAOJIYING_PASSWORD, CHAOJIYING_SOFT_ID)def crack(self):self.open()image = self.get_touclick_image()bytes_array = BytesIO()image.save(bytes_array, format='PNG')result = self.chaojiying.PostPic(bytes_array.getvalue(), CHAOJIYING_KIND)print(result)locations = self.get_points(result)self.touch_click_words(locations)self.login()try:success = self.wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '.welcome-name'), '谭仁侯'))print(success)cc = self.browser.find_element(By.CSS_SELECTOR, '.welcome-name')print(cc.text)except TimeoutException:self.chaojiying.ReportError(result['pic_id'])self.crack()def open(self):self.browser.get(self.url)login = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.login-hd-account')))login.click()time.sleep(3)username = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#J-userName')))password = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input#J-password')))username.send_keys(self.email)password.send_keys(self.password)def get_screenshot(self):screenshot = self.browser.get_screenshot_as_png()screenshot = Image.open(BytesIO(screenshot))return screenshotdef get_touclick_element(self):element = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.login-pwd-code')))return elementdef get_position(self):element = self.get_touclick_element()time.sleep(3)location = element.locationsize = element.sizetop, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']return (top, bottom, left, right)def get_touclick_image(self, name='12306.png'):top, bottom, left, right = self.get_position()screenshot = self.get_screenshot()captcha = screenshot.crop((left, top, right, bottom))captcha.save(name)return captchadef get_points(self, captcha_result):groups = captcha_result.get('pic_str').split('|')locations = [[int(number) for number in group.split(',')] for group in groups]return locationsdef touch_click_words(self, locations):for location in locations:print(location)ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(), location[0]/1.25, location[1]/1.25).click().perform()def login(self):submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'J-login')))submit.click()if __name__ == '__main__':crack = CrackTouClick()crack.crack()

chaojiying.py

import requests
from hashlib import md5class Chaojiying_Client(object):def __init__(self, username, password, soft_id):self.username = usernamepassword = password.encode('utf8')self.password = md5(password).hexdigest()self.soft_id = soft_idself.base_params = {'user': self.username,'pass2': self.password,'softid': self.soft_id,}self.headers = {'Connection': 'Keep-Alive','User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',}def PostPic(self, im, codetype):"""im: 图片字节codetype: 题目类型 参考 http://www.chaojiying.com/price.html"""params = {'codetype': codetype,}params.update(self.base_params)files = {'userfile': ('ccc.jpg', im)}r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)return r.json()def ReportError(self, im_id):"""im_id:报错题目的图片ID"""params = {'id': im_id,}params.update(self.base_params)r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)return r.json()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437927.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sharepoin学习笔记—架构系列—07nSharepoint服务(Services)与服务应用程序框架(Service Application Framework) 2

上一篇我们以问答的方式明确了Sharepoint服务的一些概念,这里我们重点来看两个方面:Sharepoint服务器构架对象模型以及Sharepoint 服务应用程序的某些拓扑结构 一、Sharepoint服务器构架对象模型 转存失败重新上传取消 二、Sharepoint 服务应用程序的某些拓扑结…

Sharepoin学习笔记—架构系列--08 Sharepoint的数据模型(DataModel)、数据管理(Data Management)与查询(Query System)

Sharepoint Foundation中的首要数据结构就是列表(List), 每个List属于某种List Type,与此类似,每个列表中的列(Column)属于某种FieldType,而每一条列表记录(List Item)属于某种Content Type.至于外部数据(External Data),即来自于…

执行 redis-dump 报错:ERROR (Errno::ENOENT): No such file or directory - ps -o rss= -p xxxxx

redis-dump 命令用于 Redis 数据的导出,执行该命令时报错如下: C:\Users\Lenovo>redis-dump -u 127.0.0.1:6379 ERROR (Errno::ENOENT): No such file or directory - ps -o rss -p 3944解决方法:找到 Ruby 安装目录下的 dump.rb 文件&a…

Sharepoint学习笔记 –架构系列—09 Sharepoint的服务器端对象模型(Server Object Model) 1.物理对象层次结构

关于Sharepoint的服务器端对象模型的内容很庞大很繁杂,而事实上,我们在这里只把最关键的对象梳理一下,我们会从三个体系来大致描述它们。 这三个体系分别是: 1、物理对象层次结构(Physical Objects Hierarchy) 2、内容层次结构(Co…

执行 redis-dump 报错:Error connecting to Redis on localhost:6379 (Redis::TimeoutError)

拿本地的 Redis 做测试,运行在 6379 端口上,使用 redis-dump -u localhost:6379 命令用于数据的导出,执行该命令时报错如下: C:\Users\Lenovo>redis-dump -u localhost:6379 Error connecting to Redis on localhost:6379 (Re…

Sharepoint学习笔记 –架构系列—10 Sharepoint的服务器端对象模型(Server Object Model) 2.内容层次结构

Sharepoint的内容层次结构(Content Hierarchy)包括表示可发布数据项(publishable items),如列表项的类,还包括表示嵌套的数据容器(nested containers of data),如列表、内容数据库、网站、网站集以及称为"Web 应用程序"…

Sharepoint学习笔记 –架构系列—11 Sharepoint的服务器端对象模型(Server Object Model) 3.服务层次结构

前面我们看了一下Sharepoint服务器对象模型的物理对象层次(Physical Objects Hierarchy)和对象内容层次(Content Hierarchy)中的相关类,这里来看看服务层次结构,其中包括表示 Web 服务(WebService)、Windows 服务(WindowService)、其他类型的服务(Icomin…

pyspider all 启动失败:ValueError: Invalid configuration

执行 pyspider all 启动命令报错如下: C:\Users\Lenovo>pyspider all e:\python\lib\site-packages\pyspider\libs\utils.py:196: FutureWarning: timeout is not supported on your platform.warnings.warn("timeout is not supported on your platform.&…

Sharepoint学习笔记 –架构系列—12 Sharepoint的客户端对象模型(Client Object Model)

前面过了一下Sharepoint的服务器端对象模型,接下来就让我们大致看看Sharepoint的客户端对象模型(Client Object Model: Client OM)。 首先需要了解的就是Sharepoint的客户端模型是在Sharepoint2010才开始引入的,之前没有这个概念。 一、为什么要引入客户…

Hexo 双线部署到 Coding Pages 和 GitHub Pages 并实现全站 HTTPS

2022-01-25 更新:博客新地址:https://www.itbob.cn/,文章距上次编辑时间较远,部分内容可能已经过时! 我的博客地址:https://www.itrhx.com/ 部署到 Coding Pages 的好处:国内访问速度更快&…

Git得基本使用方法add、commit、push、checkout以及Pull

一、Git是什么? Git是目前世界上最先进的分布式版本控制系统。 Working Directory:工作区 Index / Stage:暂存区 Repository:仓库区(或本地仓库) Remote:远程仓库 由于前面2篇文章已经简单得…

Coding Pages 申请 SSL 证书错误:urn:acme:error:unauthorized: Invalid response from http://xxxxx/

Coding Pages 申请 SSL/TLS 安全证书出现以下错误&#xff1a; urn:acme:error:unauthorized: Invalid response from http://www.xxxx.cn/.well-known/acme-challenge/ysOz9wW3U_GFPP8kRP4w8uknBZ9UfiUT7t2xpu9pDCw [185.199.111.153]: "\n\n \n <meta http-equiv“Co…

Hexo 博客提交百度、谷歌搜索引擎收录

2022-01-25 更新&#xff1a;博客新地址&#xff1a;https://www.itbob.cn/&#xff0c;文章距上次编辑时间较远&#xff0c;部分内容可能已经过时&#xff01; 文章目录● 写在前面&#xff08;必看&#xff09;● 查看网站是否被收录● 百度资源平台添加网站● 提交百度搜索●…

工作区、暂存区、版本库、远程仓库

一、概念 1、四个工作区域 Git本地有四个工作区域&#xff1a;工作目录&#xff08;Working Directory&#xff09;、暂存区(Stage/Index)、资源库(Repository或Git Directory)、git仓库(Remote Directory)。文件在这四个区域之间的转换关系如下&#xff1a; Workspace&#x…

Python3 爬虫学习笔记 C17【爬虫框架 pyspider — 基本使用】

Python3 爬虫学习笔记第十七章 —— 【爬虫框架 pyspider — 基本使用】文章目录【17.1】初识 pyspider【17.2】使用 pyspider【17.2.1】主界面【17.2.2】项目界面【17.3】使用 pyspider 爬取去哪儿网【17.3.1】爬取首页【17.3.2】信息匹配【17.3.3】抓取下一页数据【17.3.4】抓…

什么是RPA 现在都有哪些产品

作者&#xff1a;小金同学 链接&#xff1a;https://www.zhihu.com/question/264066539/answer/730946238 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 什么是RPA&#xff1f; 根据机器人流程自动化和人工智能研…

Sharepoint学习笔记—ECM系列—1 Content Type Syndication

我们可以通过Content Type Syndication来实现在Sharepoint Farm内的不同Site Collection之间共享内容类型(Content Types).也就是说&#xff0c;管理员可以为某个元数据服务(Metadata Service)指定一个网站集(Site Collection)来充当Content Type Hub&#xff0c;Content Type …

Python3 爬虫实战 — 猫眼电影TOP100【requests、lxml、Xpath、CSV 】

爬取时间&#xff1a;2019-09-23爬取难度&#xff1a;★☆☆☆☆☆请求链接&#xff1a;https://maoyan.com/board/4爬取目标&#xff1a;猫眼电影 TOP100 的电影名称、排名、主演、上映时间、评分、封面图地址&#xff0c;数据保存为 CSV 文件涉及知识&#xff1a;请求库 requ…

Sharepoint学习笔记—ECM系列--2 管理元数据服务应用Metadata Service Application

这里简单介绍一下Sharepoint2010的元数据服务应用Metadata Service Application的创建&#xff0c;修改和删除&#xff0c;在进行此类操作前&#xff0c;你必须是Sharepoint管理中心管理组的成员&#xff0c;即你有权限进入Sharepoint管理中心进行操作。 一、Metadata Service…

Python3 爬虫实战 — 豆瓣电影TOP250【requests、Xpath、正则表达式、CSV、二进制数据储存】

爬取时间&#xff1a;2019-09-27爬取难度&#xff1a;★★☆☆☆☆请求链接&#xff1a;https://movie.douban.com/top250 以及每部电影详情页爬取目标&#xff1a;爬取榜单上每一部电影详情页的数据&#xff0c;保存为 CSV 文件&#xff1b;下载所有电影海报到本地涉及知识&am…