验证码的作用
验证码的主要目的是防⽌恶意机器⼈或⾃动化程序对⽹站进⾏滥⽤、欺诈或恶意攻击。它通过要求用户识别和输⼊验证码来验证⽤⼾的“⼈类⾝份”,因为机器⽆法像⼈类⼀样正确地理解和回答验证码 中的内容。
常见的验证码
- 数字验证码:这类验证码是最为常⻅的,通常由4-6个数字组成,⽤⼾需要通过填写这些数字来完 成某些操作,如注册账⼾或登录。
- 字母验证码:字母验证码也较为常⻅,常出现在短信验证和Web⽹站的注册表单中。它的展现形式是在验证码输⼊框附近的图⽚中展⽰字⺟,⽤⼾需要识别出特定的字⺟组合来获得验证码。
- 图⽚验证码:图⽚验证码是⼀种较复杂且难以破解的验证码形式。它通常展示⼀组图片,用户需要根据系统的提示从多个选项中选择正确的图片。这种验证码增加了用户的认知负担,从而提高了安全性。
- ⽂字验证码:⽂字验证码同样常⻅于Web⽹站的应⽤,其表现形式是在验证码输⼊框附近展示⼀段⽂字,用户需要识别并输⼊其中的⽂字。
- 基于知识的验证码:这种验证码通常包含⼀些普通⺠众熟知的问题,如数学题或日期问题,以此来测试用户的知识和常识,⽽不是简单的图像识别能力。
- 动作验证码:动作验证码是通过让用户执⾏⼀定的动作来进行身份验证,这种⽅式的用户体验较好,因为它们不需要用户具备专门的知识。
验证码破解
通常情况下我们是不需要进⾏验证码破解的,因为可以直接登录进⼊网站,获取⽹站的cookie进⾏请求,可以模拟成已经登录的状态。
但是在后续可能需要重新登录认证,因为某些⽹站的设置⽤⼾信息是有期限的。我们需要重新进行手动复制,比较麻烦,这个时候我们就需要破解验证码,进行登录来获取新的登录cookie。
破解验证码我们通常使⽤⾃动化⼯具selenium以及验证码识别⼯具或者第三⽅识别平台(俗称打码平台)
模块准备
#-U 下载最新或者更新到最新版本
pip install -U selenium
# 图⽚⽂字识别提取模块
pip install -U ddddocr
# 使⽤ ddddocr 模块,可以将图⽚中的⽂字提取出来,常⻅的应⽤包括⾝份证识别、⻋牌识别、发票 识别等
如果想要快速的下载,在后面加上镜像源即可
验证selenium和chromedriver是否准备好
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service= Service(executable_path='chromedriver.exe')
driver=webdriver.Chrome(service=service)
driver.set_window_size(1100,850) #设置打开的窗口的大小
driver.get('https://www.baidu.com/?tn=88093251_87_hao_pg') #选择自动化操作页面
input() #打开之后就不会关闭
字母数字验证码识别--使用模块
古诗词文网so.gushiwen.cn/user/login.…
#找到验证码
#保存验证码
#识别验证码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from ddddocr import DdddOcr
driver=webdriver.Chrome(service=Service('../chromedriver.exe')) #选择使用的浏览器以及驱动的位置
url='https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
driver.get(url)
# 输入账号、密码
driver.find_element(By.XPATH,'//input[@name="email"]').send_keys('xxxxxxxx')
driver.find_element(By.XPATH,'//input[@name="pwd"]').send_keys('xxxxxxxx')
# 获取、保存验证码
imgCode=driver.find_element(By.ID,'imgCode') #找到验证码位置
imgCode.screenshot('img.png') #保存验证码
# 对验证码进行识别
with open('img.png',mode='rb') as file: #读取数据进行验证码的识别
yzm=DdddOcr(show_ad=False).classification(file.read()) #show_ad=False:让DdddOcr中的自带输出内容关闭,classification验证码识别的内容进行识别
# 输入验证码
driver.find_element(By.XPATH,'//input[@id="code"]').send_keys(yzm)
# 点击登录
driver.find_element(By.XPATH,'//input[@id="denglu"]').click()
input()
使用ddddocr模块进行简单的识别还是比较可靠的,比如字母,数字
字母数字验证码识别--第三方打码平台
第三方打码平台
# 超级鹰 # 注册⼀个超级鹰账号 并且登录(http://www.chaojiying.com/api-14.html)
# 充值 选择⾃定义⾦额 1:100
# 在开放⽂档中下载python⽰例
# 在⽤⼾中⼼的软件ID中创建⼀个软件ID
from user import username,password
chaojiying = Chaojiying_Client(username, password, '958015') #用户中心>>软件ID 生成一个替换 96001
im = open('a.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
print(chaojiying.PostPic(im, 1004)) #1902 验证码类型 官方网站>>价格体系 3.4+版print 后要加()
#print chaojiying.PostPic(base64_str, 1902) #此处为传入 base64代码
滑块验证码流程
目标网站:
1.找到滑块验证码的位置
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait #显示等待,需要的元素出来就继续执行下面的代码
from selenium.webdriver.support.expected_conditions import presence_of_element_located as pe #presence_of_element_located用于判断指定元素是否存在于网页之中,需要传入一个元组
driver=webdriver.Chrome(service=Service('../chromedriver.exe'))
url='https://dun.163.com/trial/sense' #网易易盾
driver.get(url)
driver.set_window_size(1100,800)
#找到点击的位置
wait=WebDriverWait(driver,20) #设置等待
#在设置的等待时间内判断页面中是否有这个元素
# wait.until(pe((By.XPATH, '//li[@class="tcapt-tabs__tab sactive"]'))).click()
wait.until(pe((By.XPATH, '//li[@captcha-type="jigsaw"]'))).click() #pe中需要传入一个元组
driver.execute_script(f'window.scrollTo(0,150)') #向下滑动
2.通过点击获得验证码
wait.until(pe((By.XPATH, '//div[@class="yidun_intelli-icon"]'))).click() #pe中需要传入一个元组
# 获得验证码并保存下来
wait.until(pe((By.XPATH, '//div[@class="yidun_bgimg"]'))).screenshot('yzm.png') #保存验证码
input()
3.识别验证距离
通过第三方打码平台,如:
#识别验证距离(这里利用的图灵)
import base64
import json
import requests
from user import username,password
# 调用图灵平台接口
def b64_api(username, password, img_path, ID):
with open(img_path, 'rb') as f:
b64_data = base64.b64encode(f.read())
b64 = b64_data.decode()
data = {"username": username, "password": password, "ID": ID, "b64": b64, "version": "3.1.1"}
data_json = json.dumps(data)
result = json.loads(requests.post("http://www.fdyscloud.com.cn/tuling/predict", data=data_json).text)
return result
#调用平台接口识别距离
result = b64_api(username=username, password=password, img_path='yzm.png', ID="78915616")
# { "code": 1, "message": "", "data": { "滑块": { "X坐标值": 28, "Y坐标值": 65 }, "缺口": { "X坐标值": 139, "Y坐标值": 66 } } }
ranges = result['data']['缺口']['X坐标值']-result['data']['滑块']['X坐标值']
print(ranges)
4.计算运动轨迹
# 运算规矩就是给传⼊⼀个距离,设置每次移动的步⻓,⽽不是直接移动到结果位置。
def get_move_track(gap):
track = [] # 移动轨迹
current = 0 # 当前位移
# 减速阈值
mid = gap * 4 / 5 # 前4/5段加速 后1/5段减速
t = 0.2 # 计算间隔
v = 0 # 初速度
while current < gap:
if current < mid:
a = 5 # 加速度为+5
else:
a = -5 # 加速度为-5
v0 = v # 初速度v0
v = v0 + a * t # 当前速度
move = v0 * t + 1 / 2 * a * t * t # 移动距离
current += move # 当前位移
track.append(round(move)) # 加⼊轨迹
return track
range_list=get_move_track(ranges)
5.滑动验证码到指定位置
# 5.滑动验证码到指定位置
from selenium.webdriver.common.action_chains import ActionChains
# yzm_img=wait.until(pe((By.XPATH,'//div[@class="yidun_slider yidun_slider--hover"]')))
yzm_img=wait.until(pe((By.XPATH,'//img[@class="yidun_jigsaw"]')))
action = ActionChains(driver) #创建一个行为链,只有行为链中才有这些操作
action.click_and_hold(yzm_img) #按住图片不放
for i in range_list:
action.move_by_offset(i,0) #滑动的x轴距离和y轴距离
action.perform() #执行按住和滑动
action.release().perform() #执行松开
print('执行完毕')
点触验证码-b站登录
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait #显示等待,找到了就继续执行下面的代码
from selenium.webdriver.support.expected_conditions import presence_of_element_located as pe #pe模块用于判断需找的元素是否存在,需要传入一个元组
from user import username,password
from time import sleep
from PIL import Image
from PIL.Image import open as pli_open,Resampling #截图
import base64
import json
import requests
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
driver=webdriver.Chrome(service=Service('../chromedriver.exe'))
driver.get('https://passport.bilibili.com/login')
driver.set_window_size(1100,800) #设置窗口大小
# 1.显示出验证码
wait=WebDriverWait(driver,20)
wait.until(pe((By.XPATH,'//div[@class="tab__form"]/div[1]/input'))).send_keys(username)
wait.until(pe((By.XPATH,'//div[@class="tab__form"]/div[3]/input'))).send_keys(password)
# wait.until(pe((By.XPATH,'//div[@class="btn_primary disabled"]'))).click()
wait.until(pe((By.XPATH,'//div[@class="btn_primary "]'))).click()
# 2.获取验证码
wait.until(pe((By.XPATH,'//img[@class="geetest_item_img"]')))
sleep(2)
driver.save_screenshot('html.png') #将验证码截图下来
# 截取验证码
image=Image.open('html.png')
image.crop((380,129,686,484)).save('yzm.png') #通过左上角坐标(477,219)和右下角(860,656)的坐标进行截图
# 拉升验证码,让验证码⼤⼩和⽹⻚⼀样,获取的数据才是⼀样的不然分辨率不⼀样
a = pli_open('yzm.png')
a.resize((306,306+48),Resampling.LANCZOS).save('yzm1.png')
# { "code": 1, "message": "", "data": { "顺序1": { "X坐标值": 240, "Y坐标值": 281 }, "顺序2": { "X坐标值": 159, "Y坐标值": 195 }, "顺序3": { "X坐标值": 59, "Y坐标值": 187 }, "顺序4": { "X坐标值": 257, "Y坐标值": 145 } } }
def b64_api(username, password, img_path, ID):
with open(img_path, 'rb') as f:
b64_data = base64.b64encode(f.read())
b64 = b64_data.decode()
data = {"username": username, "password": password, "ID": ID, "b64": b64, "version": "3.1.1"}
data_json = json.dumps(data)
result = json.loads(requests.post("http://www.fdyscloud.com.cn/tuling/predict", data=data_json).text)
return result
# 识别得到结构s
result = b64_api(username=username, password=password, img_path='yzm1.png', ID="08272733")
print(result)
# 执⾏点击操作
text = wait.until(pe((By.XPATH, '//img[@class="geetest_item_img"]')))
for k, v in result['data'].items():
print(v['X坐标值'] - 150, v['Y坐标值'] - 150 - 48)
(ActionChains(driver).move_to_element(text)
# 图⽚⾼是305 text 默认是中⼼,我们需要回到圆点,需要对x,y都进⾏调整
# -150是图⽚的⾼,-48 是图⽚上的哪⾏字的⾼度
.move_by_offset(v['X坐标值'] - 150, v['Y坐标值'] - 150 - 48)
.click().perform())
sleep(1)
print('执行完毕')
input()