整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          滑塊驗證碼識別、破解-技術(shù)詳解(JAVA)

          滑塊驗證碼識別、破解-技術(shù)詳解(JAVA)

          滑塊驗證碼是目前網(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)滑動驗證碼。下面是幾種方法:

          1 使用第三方滑動驗證碼庫

          可以使用第三方的滑動驗證碼庫,例如'vue-verify-slide'、'vue-slide-verify'等,這些庫已經(jīng)實現(xiàn)了滑動驗證碼的邏輯,我們只需要將其作為插件引入即可。

          優(yōu)點:實現(xiàn)方便,無需自己編寫邏輯代碼。

          缺點:依賴第三方庫,如果第三方庫更新不及時或存在漏洞,會影響到整個系統(tǒng)。

          2 自己編寫滑動驗證碼組件

          可以自己編寫滑動驗證碼組件,實現(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>
          

          3 使用canvas實現(xiàn)滑動驗證碼

          可以使用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í)吧

          準(zhǔn)備工具

          • pip3 install PIL
          • pip3 install opencv-python
          • pip3 install numpy

          谷歌驅(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()
          

          有能力的可以研究一下思路,然后寫出更好的解決辦法。


          主站蜘蛛池模板: 精品国产日韩亚洲一区91| 国产精品视频一区麻豆| 末成年女AV片一区二区| 无码国产伦一区二区三区视频| 亚洲熟女乱色一区二区三区| 制服美女视频一区| 亚洲熟妇AV一区二区三区浪潮| 国产成人av一区二区三区在线观看 | 精品无码综合一区| 亚洲一区二区三区久久久久| 国产福利一区二区在线视频| 亚洲日韩AV一区二区三区中文| AV怡红院一区二区三区| 色一情一乱一区二区三区啪啪高| 国产伦精品一区二区三区免费迷| 亚洲AV无码第一区二区三区| www一区二区三区| 冲田杏梨高清无一区二区| 国产高清一区二区三区| 人妻无码一区二区不卡无码av | 极品人妻少妇一区二区三区| 午夜影视日本亚洲欧洲精品一区 | 色婷婷香蕉在线一区二区| 91在线看片一区国产| 日韩人妻精品无码一区二区三区| 国产一区二区在线观看app | 日本一区二区三区四区视频| 欧美日韩精品一区二区在线观看 | 日韩精品一区二区三区中文精品 | 丰满爆乳无码一区二区三区| 麻豆国产在线不卡一区二区| 日韩一区二区三区在线| 人妻无码一区二区三区免费| 欲色影视天天一区二区三区色香欲| 亚洲一区二区成人| 深夜福利一区二区| 精品视频一区二区三区四区五区| 国产福利电影一区二区三区,亚洲国模精品一区| 日本韩国一区二区三区| 国产一区二区视频在线观看| 亚欧色一区W666天堂|