Python-实现自动旋转图片通过百度安全验证
整体思路:
(1)建立图片库。
建立一个图片库,图片库里每张图片都有一个旋转角度(用图片的名称记录每张图片到正确图片的旋转角度)。
(2)计算需要旋转的角度。
将当前要进行旋转验证的图片和图片库的图片进行比较,找出相似度最高的那张图片,就可以得到当前验证的图片需要旋转的角度。
(3)计算需要拖动的距离。
根据网页上的拖动框长度和拖动角度的比例计算出当前需要拖动button的距离。
(4)拖动button进行验证。
进行按下button-拖动距离-释放button,从而实现验证通过。
1. 建立图片库
1.1 抓取图片
找一个安全验证的页面,用selenium截取页面快照,然后裁剪出下面的图片。图片的名称用x.png标记,其中x为0,1,2,3,4,……
使用之前需要先安装selenium库,如果使用有问题可以参考链接https://blog.csdn.net/liujingliuxingjiang/article/details/120726198?spm=1001.2014.3001.5501
注意:图片保存的路径要用英文,不要包含中文,后面有些函数不支持路径含有中文的(比如相似度计算的那个函数)。
import selenium
import time
from selenium import webdriver
from PIL import Image
from selenium.webdriver.common.keys import Keys
path =r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe"
browser = webdriver.Chrome(executable_path=path)
#抓取500张图片,这些图片有很多是重复的
for i in range(0,500,1):
browser.get("https://wappass.baidu.com/static/captcha/tuxing.html?ak=2ef521ec36290baed33d66de9b16f625&backurl=http%3A%2F%2Ftieba.baidu.com%2Fp%2F3982352452×tamp=1630048735&signature=72a227fed2dc24a90bcf68b45837af6c")
time.sleep(10)#这里需要等一会儿,页面加载好,不然读取不到xpath定位的元素
print(browser.page_source)
input = browser.find_element_by_xpath('//div[@class="vcode-spin-faceboder"]')
time.sleep(5)
browser.save_screenshot(r'E:\login.png')
left=input.location['x']
top=input.location['y']
right=left+input.size['width']
bottom=top+input.size['height']
im=Image.open(r'E:\login.png')
mg=im.crop((left,top,right,bottom))
#保存截图,命名为0.png,1.png……
mg.save(r'E:\baidu_safe\{}.png'.format(i))
1.2 筛选图片
我截取并保存了500张图片,基本上是涵盖了现在的所有验证图片。这500张图片中有很多图片是一样的,只是角度不同,我们如果用人眼筛选和删除重复的图片,工作量太大了,眼睛也受不了。所以,这里还是采用脚本进行筛选。每两张图片进行比较,如果相似度大于一个阈值,就删除其中一张,保留另一张。
下面要引入相似度计算的函数,这是我直接用别人提供好的,这个算法不是我写的。https://blog.csdn.net/liu506039293/article/details/102696486这是原文的链接,感谢作者提供的算法!
#计算相似度
def img_similarity(img1_path,img2_path):
"""
:param img1_path: 图片1路径
:param img2_path: 图片2路径
:return: 图片相似度
"""
try:
# 读取图片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 初始化ORB检测器
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 提取并计算特征点
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
# knn筛选结果
matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)
# 查看最大匹配点数目
good = [m for (m, n) in matches if m.distance < 0.75 * n.distance]
# print(len(good))
# print(len(matches))
similary = len(good) / len(matches)
# print("两张图片相似度为:%s" % similary)
return similary
except:
print('无法计算两张图片相似度')
return '0'
#对于相似度高的图片,只保留其中一张图片,其他图片加入到删除的列表中,后续进行删除
def detele_same_img():
remove_list = []
for i in range(500):
for j in range(i+1,501):
img1_path = r'E:\baidu_safe\{}.png'.format(i)
img2_path = r'E:\baidu_safe\{}.png'.format(j)
similary = img_similarity(img1_path, img2_path)
if similary > 0.5:#可以根据实际情况调整这个阈值
print(similary)
print("i:{},j:{}".format(i,j))
remove_file = r'E:\baidu_safe\{}.png'.format(j)
if remove_file not in remove_list:
remove_list.append(remove_file)
#删除相似度高的图片(我们这里认为相似度超过了一个阈值就是同一张图片,只不过角度不同)
def delete_files(remove_list):
for file in remove_list:
os.remove(file)
1.3 旋转图片得到所有角度的图片
旋转图片有很多库函数可以实现,需要选择旋转后空白地方的像素采用邻近像素填充的方式进行旋转,不然图片会失真太多,影响最终的结果。
我这里采用的是的opencv库函数,需要安装opencv-python,如果安装失败,可以尝试在后面加长一点的timeout,默认是15秒超时,完整的命令:
pip install opencv-python --timeout 100。
将每张图片建立一个文件夹,文件夹的名字就是抓取图片的名字的数字部分。文件夹中的图片命名从1.png到360.png,分别对应旋转1到360度生成的新图片。
#图片旋转,生成各个角度的图片
import cv2
def rotation_img(img_path):
file_list = os.listdir(img_path)
for file in file_list:
file_index = file.replace(".png",'')
curr_file = r'E:\baidu_safe\\' + file
dir_path = r'E:\baidu_safe\all_angles\{}'.format(file_index)
if os.path.exists(dir_path):
pass
else:
os.mkdir(dir_path)#新建文件夹,文件夹的名字是原始图片名字出去.png部分
for i in range(1,361):#把一张图片旋转1度~360度,保证每个角度的图片都有一张,共360张
img = cv2.imread(curr_file)
rows, cols, channel = img.shape
M = cv2.getRotationMatrix