验证码:全自动区分计算机和人类的图灵测试
常见验证码分类:
1、汉字验证码:
2、数字 + 字母验证码:
3、算术验证码:
4、问答式验证码:
找不到,这是唯一样图
5、坐标型验证码:
6、九宫格验证码:
7、滑块验证码:
8、旋转验证码(蘑菇街):
9、语音验证码
10、短信验证码
selenium配置ie浏览器教程:https://www.cnblogs.com/misswjr/p/9453566.html
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait # 显示等待对象
from selenium.webdriver.support import expected_conditions as EC # 【某些条件为止】
from selenium.webdriver.common.by import By # 帮我们找【某个页面元素】--定义【定位器】的主要东西
def open():
'''
打开链接输入发票信息
:return:
'''
# 1请求url
driver.get('https://inv-veri.chinatax.gov.cn/')
# 2输入
# 技术点:使用显示等待做输入。
# 发票代码
wait.until(EC.presence_of_element_located((By.ID, 'fpdm'))).send_keys('044031800311')
# 发票号码
wait.until(EC.presence_of_element_located((By.ID, 'fphm'))).send_keys('08744657')
# 开票日期
wait.until(EC.presence_of_element_located((By.ID, 'kprq'))).send_keys('20191105')
# 校验码
wait.until(EC.presence_of_element_located((By.ID, 'kjje'))).send_keys('859257')
def main():
# 1、输入发票信息
open()
# 2、点击图片加载验证码
wait.until(EC.presence_of_element_located((By.XPATH, '//td[@id="imgarea"]/div/a'))).click()
# 技术点二
yzm = input('请输入验证码') # 阻塞
# 3、填入进去yzm
wait.until(EC.presence_of_element_located((By.ID, 'yzm'))).send_keys(yzm)
# 4、点击checkfp
wait.until(EC.element_to_be_clickable((By.ID, 'checkfp'))).click()
if __name__ == '__main__':
driver = webdriver.Ie()
# 1、显示等待的对象
# driver:等待对象监听哪个浏览器
# 20:最大等待时长
wait = WebDriverWait(driver, 20)
main()
程序将验证码传给打码平台的识别接口,打码平台将验证码发给后端的“佣工”进行识别,并获取识别结果。这样基于此类的人工打码平台,即可实现程序的自动化
超级鹰打码平台: http://www.chaojiying.com/
参照文档调用接口:
import hashlib
import requests
class Chaojiying(object):
def __init__(self, user, password, soft_id='903750'):
self.base_data = {
'user': user,
'pass2': str(hashlib.md5(bytes(password, encoding='utf-8')).hexdigest()),
'softid': soft_id,
}
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
'Connection': 'keep-alive',
}
def post_img(self, im, code_type):
'''
调用web接口,获取验证码图片内容
:param im: 图片的二进制流
:param code_type:验证码类型
:return:
'''
base_url = 'http://upload.chaojiying.net/Upload/Processing.php'
data = {
'codetype': code_type,
# 'file_base64':base64.b64decode(im),
}
files = {
'userfile': ('ccc.jpg', im),
}
self.base_data.update(data)
response = requests.post(base_url, data=self.base_data, headers=self.headers, files=files)
# print(response.json())
return response.json()['pic_str']
def post_error(self, pic_id):
'''
提交错误,返回题分接口
:param pic_id: 图片id,从打码平台返回的接口中获取。
:return:
'''
base_url = 'http://upload.chaojiying.net/Upload/ReportError.php'
data = {
'id': pic_id,
}
self.base_data.update(data)
response = requests.post(base_url, headers=self.headers, data=self.base_data)
return response.json()['err_str']
if __name__ == '__main__':
# fp = open('../CheckCode.png','rb')
fp = open('../code.png', 'rb')
c = Chaojiying('13016031459', 'Abc1234%')
# c.post_img(fp,1004)
c.post_img(fp, 5000)
RPA简介:
全称为机器人流程自动化(Robotic Process Automation),是一款软件产品
可模拟人在电脑上的不同系统之间操作行为,替代人在电脑前执行具有规律与重复性高的办公流程
对于RPA,也有人将它称为数字劳动力(Digital Labor),因为它擅长把工作流程中的重复操作 进行自动化。繁琐流程自动化是企业数字化转型的重要环节,RPA 能够有效优化传统办公 流程,提升工作效率,间接优化企业劳动资源配置,助力企业数字化升级
RPA价值有哪些?
(1)降低人力资源花费,人力成本节省 30%
(2)解决了繁杂的运行和业务逻辑,可以合理地回应单位专业知识基本建设的必须,解决工作人员变化的风险性
(3)让职工从繁杂、低价值的劳动者中摆脱出去,从业高些价值、创造力的工作中
(4)RPA 机器人可以二十四小时工作,提升单位的服务能力
项目描述:
RPA 财务机器人可以对收付款、审批、纳税申报、对账等多个环节实现 RPA 作业,该 项目主要实现发票真伪验证这个子功能的实现,该功能主要调用百度 AI 财务机器人接口实 现对发票信息的提取,在使用 selenium 进入发票真伪检验的网站对发票真伪进行验证
技术要点:
1、结合第三方平台(百度 AI)进行发票内容识别
2、使用 selenium 进入发票真伪检验的网站对发票真伪进行验证
3、使用打码平台进行发票真伪验证码的识别
实现步骤:
百度 AI 开发平台 URL: https://ai.baidu.com/
步骤一:登录百度 AI 开方平台,输入用户名和密码并登录
再依次选择产品服务—>人工智能—>文字识别
创建应用—>填写应用名称—>选择应用类型—>接口选择(不用选,默认即可)—>文字识别报名(默认的即可)—>填写应用描述—>点击立即创建
创建之后点击技术文档
选择调用方式,根据调用方式获取 access_token,具体参照文档实现
步骤二:在百度 AI 网站找到发票识别的接口信息
(1)创建文字识别应用,通过代码获取 token 和查验发票需要的值
(2)使用 selenium+Chrome 登录发票查验平台,输入上一步获取的数据,查验发票即可
代码实现:
import requests
import base64
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
def get_token():
'''
获取acess_tooken
:return:
'''
# client_id 为官网获取的AK, client_secret 为官网获取的SK
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=GHwkcgi0b4m0dlTwYy9xYcTm&client_secret=vm6EeSPe2a4EbhgFyt8wgwHmkLkAQMO9'
response = requests.get(host)
if response:
return response.json()['access_token']
def sb_fapiao():
'''
增值税发票识别
:return:
'''
request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/vat_invoice"
# 二进制方式打开图片文件
f = open('fapiao2.png', 'rb')
img = base64.b64encode(f.read())
params = {
"image": img}
access_token = get_token()
request_url = request_url + "?access_token=" + access_token
headers = {
'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
# print(response.text)
json_data = response.json()['words_result']
# 发票代码:InvoiceCode
InvoiceCode = json_data['InvoiceCode']
# 发票号码:InvoiceNum
InvoiceNum = json_data['InvoiceNum']
# 开票日期:InvoiceDate
InvoiceDate = json_data['InvoiceDate'].replace('年', '').replace('月', '').replace('日', '')
# 校验码:CheckCode
CheckCode = json_data['CheckCode'][-6:]
# 金额
AmountInFiguers = json_data['AmountInFiguers']
return (InvoiceCode, InvoiceNum, InvoiceDate, CheckCode, AmountInFiguers)
def verify_fapiao(infos):
'''
验证发票
:param infos: (InvoiceCode,InvoiceNum,InvoiceDate,CheckCode)
:return:
'''
driver.get('https://inv-veri.chinatax.gov.cn/')
# 2输入
# 技术点:使用显示等待做输入。
# 发票代码
wait.until(EC.presence_of_element_located((By.ID, 'fpdm'))).send_keys(infos[0])
# 发票号码
wait.until(EC.presence_of_element_located((By.ID, 'fphm'))).send_keys(infos[1])
# 开票日期
wait.until(EC.presence_of_element_located((By.ID, 'kprq'))).send_keys(infos[2])
# 校验码
wait.until(EC.presence_of_element_located((By.ID, 'kjje'))).send_keys(infos[3])
# 2、点击图片加载验证码
wait.until(EC.presence_of_element_located((By.XPATH, '//td[@id="imgarea"]/div/a'))).click()
while True:
# 清空错误内容
wait.until(EC.presence_of_element_located((By.ID, 'yzm'))).send_keys(Keys.CONTROL, 'a')
wait.until(EC.presence_of_element_located((By.ID, 'yzm'))).send_keys(Keys.CONTROL, 'x')
# 技术点二
yzm = input('请输入验证码,输入exit继续程序') # 阻塞
if yzm == 'exit':
break
# 3、填入进去yzm
wait.until(EC.presence_of_element_located((By.ID, 'yzm'))).send_keys(yzm)
# 4、点击checkfp
wait.until(EC.element_to_be_clickable((By.ID, 'checkfp'))).click()
if infos[-1] in driver.page_source:
print('发票为正!')
else:
print('发票有误!')
if __name__ == '__main__':
driver = webdriver.Ie()
wait = WebDriverWait(driver, 20)
# 调用百度ai接口识别发票
infos = sb_fapiao()
# 进行税务平台验证
verify_fapiao(infos)
分析问题:
要点一:滑动多远----就是滑动距离如何计算
要点二:人的滑动操作,先加速后减速的过程
计算机如何做移动:
只需要告诉坐标点位置,计算机只需要在对应点的位置改变起像素点的值即可显示,就是瞬移的
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
def get_tracks(distance):
'''
通过加速减速物理模型,讲一个距离划分距离片段。
:param distance: 距离
:return: 【1,2,3,4,6,9,6,4,2,1】
'''
# 速度:当前速度
v = 0
# 定义时间间隔
# 像素是没有小数。
t = 0.3
tracks = []
# 当前距离:当前已经移动了多少
current = 0
mid = 0.6 * distance
while current < distance:
# 循环移动
v0 = v
if current < mid:
a = 3
else:
a = -2
s = v0 * t + 0.5 * a * t * t
tracks.append(round(s))
current += s
v = v0 + a * t
return tracks
def slider_code(driver):
'''
通过滑动验证码
:param driver: 带有滑动验证码的dirver
:return:
'''
print('-----开始处理验证码!------')
# 切入frame
driver.switch_to.frame(0)
# 1、找到滑块
slider = driver.find_element_by_xpath('//*[@id="tcaptcha_drag_thumb"]')
print(slider)
while True:
# 2、使用鼠标操作点住滑块并且使鼠标悬浮
# perform:鼠标悬浮
# click_and_hold:点住并且保持。
ActionChains(driver).click_and_hold(on_element=slider).perform()
# 3、计算移动的距离
# 235
# move_by_offset:通过偏移量来移动
ActionChains(driver).move_by_offset(xoffset=100, yoffset=0).perform()
# 4、移动的过程使用先加速后减速的过程
tracks = get_tracks(135)
print(tracks)
for s in tracks:
ActionChains(driver).move_by_offset(xoffset=s, yoffset=0).perform()
# 5、移动到目标位置之后释放鼠标(悬浮释放)
ActionChains(driver).release().perform()
# 是否登录成功
if not driver.title == '登录豆瓣':
break
# 点击刷新
driver.find_element_by_id('reload').click()
time.sleep(1)
return True
def main():
# 1、请求豆瓣登录页面
driver.get('https://accounts.douban.com/passport/login')
# 2、点击密码登录
# 问题:找不到密码登录
# 原因:有iframe标签
# 解决:切入iframe
# driver.switch_to.frame(0)
wait.until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="account"]/div[2]/div[2]/div/div[1]/ul[1]/li[2]'))).click()
# 3、输入用户名和密码
wait.until(EC.presence_of_element_located((By.ID, 'username'))).send_keys('17673277948')
wait.until(EC.presence_of_element_located((By.ID, 'password'))).send_keys('zsc17673277948')
# 4、点击登录
wait.until(
EC.element_to_be_clickable((By.XPATH, '//*[@id="account"]/div[2]/div[2]/div/div[2]/div[1]/div[4]/a'))).click()
time.sleep(2)
if driver.title == '登录豆瓣':
# 有验证码
if slider_code(driver):
print('登录成功!')
else:
print('登录失败!')
else:
print('登录成功!')
if __name__ == '__main__':
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 20)
# 最大化
driver.maximize_window()
main()
案列分析:
代码实现:
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from PIL import Image
def get_tracks(distance):
'''
通过加速减速物理模型,讲一个距离划分距离片段。
:param distance: 距离
:return: 【1,2,3,4,6,9,6,4,2,1】
'''
# 速度:当前速度
v = 0
# 定义时间间隔
# 像素是没有小数。
t = 0.3
tracks = []
# 当前距离:当前已经移动了多少
current = 0
mid = 0.6 * distance
while current < distance:
# 循环移动
v0 = v
if current < mid:
a = 2
else:
a = -2
s = v0 * t + 0.5 * a * t * t
tracks.append(round(s))
current += s
v = v0 + a * t
return tracks
def open():
'''
打开浏览器进行用户名和密码填充,出现验证码
:return:
'''
driver.get('https://account.cnblogs.com/signin?returnUrl=https:%2F%2Fwww.cnblogs.com%2F')
# 填充用户名和密码
wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="mat-input-0"]'))).send_keys('markshui')
wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="mat-input-1"]'))).send_keys('zsc17673277948')
# 点击登录按钮
wait.until(EC.element_to_be_clickable((By.XPATH,
'/html/body/app-root/div/mat-sidenav-container/mat-sidenav-content/div/div/app-sign-in/app-content-container/mat-card/div/form/div/button'))).click()
time.sleep(5)
def is_similar(x, y, image1, image2):
'''
判断image1和image2在(x,y)位置的像素点是否一致。
:param x:
:param y:
:param image1:
:param image2:
:return:
'''
pixel1 = image1.getpixel((x, y))
pixel2 = image2.getpixel((x, y))
# print(pixel1,pixel2)#(149, 177, 145, 255) (149, 177, 145, 255)
if abs(pixel1[0] - pixel2[0]) >= 30 and abs(pixel1[1] - pixel2[1]) >= 30 and abs(pixel1[2] - pixel2[2]) >= 30:
print(pixel1, pixel2)
return False
return True
def calculate_distance(image1, image2):
'''
通过两张图片,计算起计算点的差异。
:param image1:
:param iamge2:
:return: (x,y)
'''
for i in range(190):
for j in range(150):
if is_similar(i, j, image1, image2) == False:
return (i, j)
return -1
def get_distance():
'''
获取滑动的距离
:return:
'''
# 1、全局截屏
driver.save_screenshot('total_1.png')
# 2、找到抠图的参数
yz_element = driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]')
size = yz_element.size
location = yz_element.location
# print(size)#{'height': 160, 'width': 260}
# print(location)#{'x': 544.5, 'y': 176.984375}
params_crop = (
location['x'] + 65, location['y'] + 5, location['x'] + size['width'] - 5, location['y'] + size['height'] - 5)
# 3、抠图--有缺口局部图片--image_part1.png
image_t1 = Image.open('total_1.png')
image_part1 = image_t1.crop(params_crop)
image_part1.save('image_part1.png')
# 4、更改js,出现原图--截图得到无缺的图片:image_part2.png
driver.execute_script('document.getElementsByClassName("geetest_canvas_fullbg")[0].style="display: block"')
driver.save_screenshot('total_2.png')
image_t2 = Image.open('total_2.png')
image_part2 = image_t2.crop(params_crop)
image_part2.save('image_part2.png')
driver.execute_script('document.getElementsByClassName("geetest_canvas_fullbg")[0].style="display: none"')
x, y = calculate_distance(image_part1, image_part2)
return x + 60
def slider_code():
'''
处理滑动验证码
:return:
'''
print('----开始处理验证码------')
# 1、找到滑块
slider = wait.until(
EC.presence_of_element_located((By.XPATH, '/html/body/div[4]/div[2]/div[6]/div/div[1]/div[2]/div[2]')))
# slider = driver.find_element_by_xpath('/html/body/div[4]/div[2]/div[6]/div/div[1]/div[2]/div[2]')
print(slider)
while True:
# 2、使用鼠标点出滑块并且保持悬浮
ActionChains(driver).click_and_hold(on_element=slider).perform()
# 3、开始滑动--长度需要计算---计算滑动的距离
distance = get_distance()
print(distance)
# 4、按照距离进行滑动(先加速后减速)
ActionChains(driver).move_by_offset(xoffset=distance * 0.2, yoffset=0).perform()
tracks = get_tracks(distance * 0.8)
print(tracks)
for s in tracks:
ActionChains(driver).move_by_offset(xoffset=s, yoffset=0).perform()
# #5、释放鼠标。
time.sleep(1)
ActionChains(driver).release().perform()
time.sleep(3)
if not '用户登录' in driver.title:
break
# 点击刷新验证码
driver.find_element_by_xpath('//a[@class="geetest_refresh_1"]').click()
time.sleep(2)
return True
def main():
# 打开浏览器进行用户名和密码填充,出现验证码
open()
# 处理滑动验证码
if '用户登录' in driver.title:
if slider_code():
print('登录成功!')
if __name__ == '__main__':
driver = webdriver.Chrome()
driver.maximize_window()
wait = WebDriverWait(driver, 20)
main()