滑塊驗證碼是目前網(wǎng)絡(luò)上使用最多的,也是體驗相對來說比較好的一種驗證碼。但爬蟲和反爬蟲就像矛和盾一樣的關(guān)系相互促進(jìn)相互影響,互聯(lián)網(wǎng)技術(shù)就是在這樣的不斷碰撞中向前發(fā)展。
結(jié)合我自己的個人工作經(jīng)驗,來聊聊滑塊驗證碼,我們就拿京東登陸頁面的滑塊驗證舉例,進(jìn)行詳細(xì)分解學(xué)習(xí)。
滑塊驗證碼樣例
目標(biāo):通過算法找到需要滑動的滑塊(下文一律叫切片區(qū))距離背景目標(biāo)區(qū)域(下文一律叫背景區(qū))的距離,然后自動拖動完成拼接。
一、利用Chrome-F12的開發(fā)者工具來定位滑塊驗證碼的請求地址:
1、在google瀏覽器中打開對應(yīng)的網(wǎng)站,進(jìn)入到滑塊驗證碼頁面
2、在驗證碼頁面按F12,進(jìn)入Network區(qū)
3、點擊驗證碼右上角的換一張(圖中標(biāo)號為1),目的是捕獲驗證碼的請求地址
4、在name區(qū)可以看到多個情況地址,找到其中的驗證碼請求地址,這里是g.html(圖中標(biāo)號為2)
5、在Headers表頭可以看到對應(yīng)此鏈接地址的情況地址,以及請求方式,這里是GET請求
(注:后期可以通過JS或者Java等模擬網(wǎng)站GET請求來獲取驗證碼信息)
定位滑塊驗證碼的請求地址
二、分析、查找"切片區(qū)"和"背景區(qū)"的對應(yīng)圖片數(shù)據(jù)信息:
1、點擊開發(fā)者工具中的Response來查看請求的返回值
2、這里是一個JSON串格式,其中bg對應(yīng)的值就是背景圖片區(qū)域的base64字符串值,patch對應(yīng)的值就是切片區(qū)base64字符串值.
切片區(qū)"和"背景區(qū)"數(shù)據(jù)信息
3、將這些base64字符串值轉(zhuǎn)換成圖片,我們看一下背景區(qū)和切片區(qū)字符串對應(yīng)的具體圖像:
(背景區(qū))
(切片區(qū))
//切片對應(yīng)的base64String
String sliceImg="iVBORw0KGgoAAAANSUhEUgAAADIAAA.....";//內(nèi)容太多省略,自己從瀏覽器中獲取即可
//背景區(qū)對應(yīng)的base64String
String bgImg="iVBORw0KGgoAAAANSUhE....";//內(nèi)容太多省略,自己從瀏覽器中獲取即可
//背景區(qū)
BufferedImage biBuffer=base64StringToImg(bgImg);
//切片區(qū)
BufferedImage sliceBuffer=base64StringToImg(sliceImg);
//將圖片輸出到本地查看
ImageIO.write(biBuffer,
"png", new File("E:\\bgImg.png"));
ImageIO.write(sliceBuffer,
"png", new File("E:\\sliceImg.png"));
/**
* base64字符串轉(zhuǎn)存圖片
* @param base64String base64字符串
* @return BufferedImage
*/
public static BufferedImage base64StringToImg(final String base64String) {
try {
BASE64Decoder decoder=new BASE64Decoder();
byte[] bytes=decoder.decodeBuffer(base64String);
ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
return ImageIO.read(bais);
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
三、(重點,核心)利用orc模板匹配算法進(jìn)行匹配,查找最相似區(qū)域,也就是我們的期望的坐標(biāo)點:
廢話不多說,直接上代碼:
import static com.googlecode.javacv.cpp.opencv_core.CV_32FC1;
import static com.googlecode.javacv.cpp.opencv_core.cvCreateMat;
import static com.googlecode.javacv.cpp.opencv_core.cvMinMaxLoc;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_TM_CCOEFF_NORMED;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvMatchTemplate;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import com.googlecode.javacv.cpp.opencv_core;
import com.googlecode.javacv.cpp.opencv_core.CvMat;
import com.googlecode.javacv.cpp.opencv_core.CvSize;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.cpp.opencv_imgproc;
import sun.misc.BASE64Decoder;
public class Test {
public static void main(String[] args) throws IOException {
//切片對應(yīng)的base64String
String sliceImg="iVBORw0KGgoAAAANSUhEUgAAADIAAA.....";//內(nèi)容太多省略,自己從瀏覽器中獲取即可
//背景區(qū)對應(yīng)的base64String
String bgImg="iVBORw0KGgoAAAANSUhE....";//內(nèi)容太多省略,自己從瀏覽器中獲取即可
// 背景區(qū)
BufferedImage biBuffer=base64StringToImg(bgImg);
// 切片區(qū)
BufferedImage sliceBuffer=base64StringToImg(sliceImg);
// 由于切片矩形區(qū)域存在透明區(qū)域,所以預(yù)處理將透明區(qū)域變成白色,方便后面對圖片二值化處理。
// (重點:如果這里不對透明區(qū)域預(yù)處理,切片預(yù)處理后將只有一種顏色導(dǎo)致匹配失敗)
int white=new Color(255, 255, 255).getRGB();
for (int x=0; x < sliceBuffer.getWidth(); x++) {
for (int y=0; y < sliceBuffer.getHeight(); y++) {
if ((sliceBuffer.getRGB(x, y) >> 24)==0) {
sliceBuffer.setRGB(x, y, white);
}
}
}
IplImage sourceImage=IplImage.createFrom(biBuffer);
IplImage targetImage=IplImage.createFrom(sliceBuffer);
CvMat sourceMat=sourceImage.asCvMat();
CvMat targetMat=targetImage.asCvMat();
// 模板匹配算法,根據(jù)目標(biāo)圖片在背景圖片中查找相似的區(qū)域
List<Rectangle> a=matchTemplateTest(sourceMat, targetMat);
// 取第一個值,也就是匹配到的最相識的區(qū)域,可以定位目標(biāo)坐標(biāo)
// 也是我們期望的坐標(biāo)點
Rectangle rec=a.get(0);
// 下面是驗證,將識別到的區(qū)域用紅色矩形框標(biāo)識出來,進(jìn)行驗證看是否正確
Graphics g=biBuffer.getGraphics();
// 畫筆顏色
g.setColor(Color.RED);
// 矩形框(原點x坐標(biāo),原點y坐標(biāo),矩形的長,矩形的寬)
g.drawRect(rec.x, rec.y, rec.width, rec.height);
g.dispose();
//輸出到本地,驗證區(qū)域查找是否正確
FileOutputStream out=new FileOutputStream("d:\\checkImage.png");
ImageIO.write(biBuffer, "png", out);
}
/**
* 模板匹配算法,根據(jù)目標(biāo)圖片在背景圖片中查找相似的區(qū)域
* @param sourceMat 背景區(qū)域圖片數(shù)組矩陣
* @param targetMat 切片目標(biāo)區(qū)域圖片數(shù)組矩陣
* @return 坐標(biāo)點集合
*/
public static List<Rectangle> matchTemplateTest(CvMat sourceMat, CvMat targetMat) {
List<Rectangle> rtn=new ArrayList<Rectangle>();
//對圖象進(jìn)行單通道、二值化處理
CvMat source=opencv_core.cvCreateMat(sourceMat.rows(), sourceMat.cols(), opencv_core.CV_8UC1);
CvMat target=opencv_core.cvCreateMat(targetMat.rows(), targetMat.cols(), opencv_core.CV_8UC1);
opencv_imgproc.cvCvtColor(sourceMat, source, opencv_imgproc.CV_BGR2GRAY);
opencv_imgproc.cvCvtColor(targetMat, target, opencv_imgproc.CV_BGR2GRAY);
CvSize targetSize=target.cvSize();
CvSize sourceSize=source.cvSize();
CvSize resultSize=new CvSize();
resultSize.width(sourceSize.width() - targetSize.width() + 1);
resultSize.height(sourceSize.height() - targetSize.height() + 1);
CvMat result=cvCreateMat(resultSize.height(), resultSize.width(), CV_32FC1);
//利用模板匹配算法進(jìn)行查找
cvMatchTemplate(source, target, result, CV_TM_CCOEFF_NORMED);
opencv_core.CvPoint maxLoc=new opencv_core.CvPoint();
opencv_core.CvPoint minLoc=new opencv_core.CvPoint();
double[] minVal=new double[2];
double[] maxVal=new double[2];
//找出圖片數(shù)據(jù)中最大值及最小值的數(shù)據(jù)
cvMinMaxLoc(result, minVal, maxVal, minLoc, maxLoc, null);
Rectangle rec=new Rectangle(maxLoc.x(), maxLoc.y(), target.cols(), target.rows());
//將查找到的坐標(biāo)按最優(yōu)值順序放入數(shù)組
rtn.add(rec);
source.release();
target.release();
result.release();
opencv_core.cvReleaseMat(result);
opencv_core.cvReleaseMat(source);
opencv_core.cvReleaseMat(target);
source=null;
target=null;
result=null;
return rtn;
}
我們看一下識別到的結(jié)果區(qū)域(紅色矩形標(biāo)識就是有系統(tǒng)自動識別出來的)霸氣不霸氣:
系統(tǒng)自動識別出來的區(qū)域坐標(biāo)
四、根據(jù)第三步得到的移動坐標(biāo)點進(jìn)行坐標(biāo)移動(這太小菜了,就不大篇幅在這里啰嗦了,可以使用你知道的任何技術(shù)進(jìn)行模擬坐標(biāo)移動),我用autoit進(jìn)行舉例;
//autoit代碼塊
//移動鼠標(biāo)指針。
MouseMove ( x, y [, 速度] )
//參數(shù)說明:
x:要移動到的目標(biāo)位置的 X 坐標(biāo)。
y:要移動到的目標(biāo)位置的 Y 坐標(biāo)。
速度:鼠標(biāo)移動速度,可設(shè)數(shù)值范圍在 1(最快)和 100(最慢)之間。若設(shè)置速度為 0 則立即移動鼠標(biāo)到指定位置。默認(rèn)速度為 10。
ue可以通過插件來實現(xiàn)滑動驗證碼。下面是幾種方法:
可以使用第三方的滑動驗證碼庫,例如'vue-verify-slide'、'vue-slide-verify'等,這些庫已經(jīng)實現(xiàn)了滑動驗證碼的邏輯,我們只需要將其作為插件引入即可。
優(yōu)點:實現(xiàn)方便,無需自己編寫邏輯代碼。
缺點:依賴第三方庫,如果第三方庫更新不及時或存在漏洞,會影響到整個系統(tǒng)。
可以自己編寫滑動驗證碼組件,實現(xiàn)自定義的UI和邏輯。
優(yōu)點:可以自由定制UI和邏輯。
缺點:需要編寫大量的邏輯代碼,工作量較大。
下面是一個自己編寫的滑動驗證碼組件的示例:
<template>
<div class="slider-verify">
<div class="slider-bar" :style="{left: thumbLeft}">
<div class="slider-thumb" @mousedown="onMouseDown"></div>
</div>
<div class="slider-mask"></div>
</div>
</template>
<script>
export default {
data() {
return {
isDragging: false, // 是否正在拖動滑塊
thumbLeft: 0, // 滑塊左邊距
maxWidth: 280, // 滑塊最大可移動距離
dragStartX: 0, // 開始拖動時鼠標(biāo)的x坐標(biāo)
dragOffsetX: 0, // 鼠標(biāo)相對于滑塊左邊緣的偏移量
};
},
methods: {
onMouseDown(e) {
this.isDragging=true;
this.dragStartX=e.clientX;
this.dragOffsetX=e.offsetX;
},
onMouseMove(e) {
if (this.isDragging) {
const distance=e.clientX - this.dragStartX;
const thumbLeft=Math.min(Math.max(distance - this.dragOffsetX, 0), this.maxWidth);
this.thumbLeft=`${thumbLeft}px`;
}
},
onMouseUp(e) {
this.isDragging=false;
if (parseInt(this.thumbLeft)===this.maxWidth) {
this.$emit('success');
} else {
this.thumbLeft='0px';
}
},
},
mounted() {
window.addEventListener('mousemove', this.onMouseMove);
window.addEventListener('mouseup', this.onMouseUp);
},
beforeDestroy() {
window.removeEventListener('mousemove', this.onMouseMove);
window.removeEventListener('mouseup', this.onMouseUp);
},
};
</script>
<style scoped>
.slider-verify {
position: relative;
width: 300px;
height: 40px;
border-radius: 20px;
overflow: hidden;
}
.slider-bar {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #eee;
transition: all 0.3s ease-out;
}
.slider-thumb {
position: absolute;
left: 0;
top: 50%;
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease-out;
}
.slider-mask {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 20px;
}
</style>
可以使用canvas繪制滑動驗證碼,將滑塊拖動的距離作為驗證依據(jù)。
優(yōu)點:可以自由定制UI和邏輯,滑動效果更流暢。
缺點:需要對canvas有一定的了解,對性能有一定的影響。
下面是一個使用canvas實現(xiàn)的滑動驗證碼的示例:
<template>
<div class="canvas-verify">
<canvas ref="canvas" :width="canvasWidth" :height="canvasHeight" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"></canvas>
</div>
</template>
<script>
export default {
data() {
return {
isDragging: false, // 是否正在拖動滑塊
thumbLeft: 0, // 滑塊左邊距
canvasWidth: 300, // canvas寬度
canvasHeight: 150, // canvas高度
maxWidth: 250, // 滑塊最大可移動距離
dragStartX: 0, // 開始拖動時鼠標(biāo)的x坐標(biāo)
dragOffsetX: 0, // 鼠標(biāo)相對于滑塊左邊緣的偏移量
canvasContext: null, // canvas context
imagePath: '', // 背景圖路徑
};
},
methods: {
onMouseDown(e) {
if (this.isDragging) {
return;
}
const rect=this.$refs.canvas.getBoundingClientRect();
this.isDragging=true;
this.dragStartX=e.clientX - rect.left;
this.dragOffsetX=this.dragStartX - this.thumbLeft;
},
onMouseMove(e) {
if (this.isDragging) {
const rect=this.$refs.canvas.getBoundingClientRect();
const distance=e.clientX - rect.left - this.dragOffsetX;
const thumbLeft=Math.min(Math.max(distance, 0), this.maxWidth);
this.thumbLeft=thumbLeft;
this.draw();
}
},
onMouseUp(e) {
if (this.isDragging) {
this.isDragging=false;
if (this.thumbLeft===this.maxWidth) {
this.$emit('success');
} else {
this.thumbLeft=0;
this.draw();
}
}
},
draw() {
this.canvasContext.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
// 繪制背景圖
const image=new Image();
image.src=this.imagePath;
image.onload=()=> {
this.canvasContext.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight);
// 繪制滑塊
this.canvasContext.fillStyle='#ccc';
this.canvasContext.fillRect(this.thumbLeft, 50, 50, 50);
};
},
},
mounted() {
// 獲取canvas context
this.canvasContext=this.$refs.canvas.getContext('2d');
// 加載背景圖
this.imagePath='https://picsum.photos/300/150/?random';
const image=new Image();
image.src=this.imagePath;
image.onload=()=> {
this.draw();
};
},
beforeUnmount() {
this.canvasContext=null;
},
};
</script>
<style scoped>
.canvas-verify {
position: relative;
}
</style>
這個示例中,滑塊使用了一個矩形代替,顏色為灰色。使用canvas實現(xiàn)滑動驗證碼需要對canvas有一定的了解,同時對性能也有一定的影響。但是可以自由定制UI和邏輯,實現(xiàn)更靈活。
以上是三種常見的實現(xiàn)滑動驗證碼的方法,每種方法都有其優(yōu)點和缺點。使用CSS實現(xiàn)最簡單,但是不太安全;使用canvas實現(xiàn)最靈活,但是需要對canvas有一定的了解;使用第三方庫可以更快速地實現(xiàn),但是需要依賴第三方庫。具體使用哪種方法應(yīng)該根據(jù)實際情況選擇,權(quán)衡各種因素。
本文的文字及圖片來源于網(wǎng)絡(luò),僅供學(xué)習(xí)、交流使用,不具有任何商業(yè)用途,版權(quán)歸原作者所有,如有問題請及時聯(lián)系我們以作處理。
作者:卡卡叮
PS:如有需要Python學(xué)習(xí)資料的小伙伴可以私信小編
這篇文章主要介紹了python模擬嗶哩嗶哩滑塊登入驗證的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
谷歌驅(qū)動
建議指定清華源下載速度會更快點
使用方法 :
pip3 install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/
谷歌驅(qū)動
谷歌驅(qū)動下載鏈接 :http://npm.taobao.org/mirrors/chromedriver/
本篇文章采用的是cv2的Canny邊緣檢測算法進(jìn)行圖像識別匹配。
Canny邊緣檢測算法參考鏈接:https://www.jb51.net/article/185336.htm
具體使用的是Canny的matchTemplate方法進(jìn)行模糊匹配,匹配方法用CV_TM_CCOEFF_NORMED歸一化相關(guān)系數(shù)匹配。得出的max_loc就是匹配出來的位置信息。從而達(dá)到位置的距離。
難點
由于圖像采用放大的效果匹配出的距離偏大,難以把真實距離,并存在誤差。
由于嗶哩嗶哩滑塊驗證進(jìn)一步采取做了措施,如果滑動時間過短,會導(dǎo)致驗證登入失敗。所以我這里采用變速的方法,在相同時間內(nèi)滑動不同的距離。
誤差的存在是必不可少的,有時會導(dǎo)致驗證失敗,這都是正常現(xiàn)象。
1.實例化谷歌瀏覽器 ,并打開嗶哩嗶哩登入頁面。
2.點擊登陸,彈出滑動驗證框。
3.全屏截圖、后按照尺寸裁剪各兩張。
5.模糊匹配兩張圖片,從而獲取匹配結(jié)果以及位置信息 。
6.將位置信息與頁面上的位移距離轉(zhuǎn)化,并盡可能少的減少誤差 。
7.變速的拖動滑塊到指定位置,從而達(dá)到模擬登入。
庫安裝好后,然后填寫配置區(qū)域后即可運行。
from PIL import Image
from time import sleep
from selenium import webdriver
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
import cv2
import numpy as np
import math
############ 配置區(qū)域 #########
zh='' #賬號
pwd='' #密碼
# chromedriver的路徑
chromedriver_path="C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
####### end #########
options=webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--window-size=1020,720')
# options.add_argument('--start-maximized') # 瀏覽器窗口最大化
options.add_argument('--disable-gpu')
options.add_argument('--hide-scrollbars')
options.add_argument('test-type')
options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors",
"enable-automation"]) # 設(shè)置為開發(fā)者模式
driver=webdriver.Chrome(options=options, executable_path=chromedriver_path)
driver.get('https://passport.bilibili.com/login')
# 登入
def login():
driver.find_element_by_id("login-username").send_keys(zh)
driver.find_element_by_id("login-passwd").send_keys(pwd)
driver.find_element_by_css_selector("#geetest-wrap > div > div.btn-box > a.btn.btn-login").click()
print("點擊登入")
# 整個圖,跟滑塊整個圖
def screen(screenXpath):
img=WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.XPATH, screenXpath))
)
driver.save_screenshot("allscreen.png") # 對整個瀏覽器頁面進(jìn)行截圖
left=img.location['x']+160 #往右
top=img.location['y']+60 # 往下
right=img.location['x'] + img.size['width']+230 # 往左
bottom=img.location['y'] + img.size['height']+110 # 往上
im=Image.open('allscreen.png')
im=im.crop((left, top, right, bottom)) # 對瀏覽器截圖進(jìn)行裁剪
im.save('1.png')
print("截圖完成1")
screen_two(screenXpath)
screen_th(screenXpath)
matchImg('3.png','2.png')
# 滑塊部分圖
def screen_two(screenXpath):
img=WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.XPATH, screenXpath))
)
left=img.location['x'] + 160
top=img.location['y'] + 80
right=img.location['x'] + img.size['width']-30
bottom=img.location['y'] + img.size['height'] + 90
im=Image.open('allscreen.png')
im=im.crop((left, top, right, bottom)) # 對瀏覽器截圖進(jìn)行裁剪
im.save('2.png')
print("截圖完成2")
# 滑塊剩余部分圖
def screen_th(screenXpath):
img=WebDriverWait(driver, 20).until(
EC.visibility_of_element_located((By.XPATH, screenXpath))
)
left=img.location['x'] + 220
top=img.location['y'] + 60
right=img.location['x'] + img.size['width']+230
bottom=img.location['y'] + img.size['height'] +110
im=Image.open('allscreen.png')
im=im.crop((left, top, right, bottom)) # 對瀏覽器截圖進(jìn)行裁剪
im.save('3.png')
print("截圖完成3")
#圖形匹配
def matchImg(imgPath1,imgPath2):
imgs=[]
#展示
sou_img1=cv2.imread(imgPath1)
sou_img2=cv2.imread(imgPath2)
# 最小閾值100,最大閾值500
img1=cv2.imread(imgPath1, 0)
blur1=cv2.GaussianBlur(img1, (3, 3), 0)
canny1=cv2.Canny(blur1, 100, 500)
cv2.imwrite('temp1.png', canny1)
img2=cv2.imread(imgPath2, 0)
blur2=cv2.GaussianBlur(img2, (3, 3), 0)
canny2=cv2.Canny(blur2, 100, 500)
cv2.imwrite('temp2.png', canny2)
target=cv2.imread('temp1.png')
template=cv2.imread('temp2.png')
# 調(diào)整大小
target_temp=cv2.resize(sou_img1, (350, 200))
target_temp=cv2.copyMakeBorder(target_temp, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
template_temp=cv2.resize(sou_img2, (200, 200))
template_temp=cv2.copyMakeBorder(template_temp, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
imgs.append(target_temp)
imgs.append(template_temp)
theight, twidth=template.shape[:2]
# 匹配跟拼圖
result=cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
cv2.normalize( result, result, 0, 1, cv2.NORM_MINMAX, -1 )
min_val, max_val, min_loc, max_loc=cv2.minMaxLoc(result)
# 畫圈
cv2.rectangle(target,max_loc,(max_loc[0]+twidth,max_loc[1]+theight),(0,0,255),2)
target_temp_n=cv2.resize(target, (350, 200))
target_temp_n=cv2.copyMakeBorder(target_temp_n, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=[255, 255, 255])
imgs.append(target_temp_n)
imstack=np.hstack(imgs)
cv2.imshow('windows'+str(max_loc), imstack)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 計算距離
print(max_loc)
dis=str(max_loc).split()[0].split('(')[1].split(',')[0]
x_dis=int(dis)+135
t(x_dis)
#拖動滑塊
def t(distances):
draggable=driver.find_element_by_css_selector('div.geetest_slider.geetest_ready > div.geetest_slider_button')
ActionChains(driver).click_and_hold(draggable).perform() #抓住
print(driver.title)
num=getNum(distances)
sleep(3)
for distance in range(1,int(num)):
print('移動的步數(shù): ',distance)
ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
sleep(0.25)
ActionChains(driver).release().perform() #松開
# 計算步數(shù)
def getNum(distances):
p=1+4*distances
x1=(-1 + math.sqrt(p)) / 2
x2=(-1 - math.sqrt(p)) / 2
print(x1,x2)
if x1>=0 and x2<0:
return x1+2
elif(x1<0 and x2>=0):
return x2+2
else:
return x1+2
def main():
login()
sleep(5)
screenXpath='/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/div/canvas[2]'
screen(screenXpath)
sleep(5)
if __name__=='__main__':
main()
有能力的可以研究一下思路,然后寫出更好的解決辦法。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。