tsu.xxw 发表于 2022-3-5 22:07

python怎样过滑块?

请问python爬虫怎样过滑块呢,selenium方法除外
类似于这种的

zhiwoda 发表于 2022-3-5 22:18

本帖最后由 zhiwoda 于 2022-3-5 23:17 编辑

原理:先把两张图片下载下来,然后用opencv灰度化,计算滑块位置,然后以非匀速拖过去,录了一个GIF可以看下效果
public static boolean handleVerifyCode(WebDriver driver, int nSort) {

                boolean bfinal = false;

                try {

                        TXT.System_out_println("Hello,handleVerifyCode...");

                        if (!DATA_HTML_HASHMAP.containsKey("验证码背景图Tag") || !DATA_HTML_HASHMAP.containsKey("验证码滑块Tag")
                                        || !DATA_HTML_HASHMAP.containsKey("验证码拖动滑块Tag") || !DATA_HTML_HASHMAP.containsKey("验证码图片资源路径Txt")) {
                              TXT.System_out_println("获取验证码Tag失败,未设置...throw new Exception()");
                              throw new Exception();
                        }

                        String sBgName = DATA_HTML_HASHMAP.get("验证码背景图Tag");
                        String sBlockName = DATA_HTML_HASHMAP.get("验证码滑块Tag");
                        String sDragName = DATA_HTML_HASHMAP.get("验证码拖动滑块Tag");

                        // 创建文件夹
                        String sVerifyFile = DATA_HTML_HASHMAP.get("验证码图片资源路径Txt") + nSort;
                        File fileVerify = new File(sVerifyFile);
                        if (!fileVerify.exists()) {
                              fileVerify.mkdirs();
                        }

                        // 存储验证码图片的顺序名称
                        int nCurSort = 0;
                        if (DATA_VERIFY_HASHMAP.containsKey(nSort)) {
                              nCurSort = DATA_VERIFY_HASHMAP.get(nSort);
                        }

                        // OpenCV对象
                        Mat matSlideBlock = null; // 滑块对象
                        Mat matSlideBg = null; // 背景图对象
                        Mat matResult = null; // 叠加对象
                        List<Integer> moveTrack = null; // 移动轨迹
                        Actions actions = null; // 拖拽对象
                        int x = 0; // 计算后的滑块横坐标
                        int y = 0; // 计算后的滑块纵坐标
                        int tma = 0;
                        int tmb = 0;

                        if (!DATA_HTML_HASHMAP.containsKey("验证码验证过于频繁Txt") || !DATA_HTML_HASHMAP.containsKey("验证码验证服务异常Txt")
                                        || !DATA_HTML_HASHMAP.containsKey("验证码验证验证通过Txt")
                                        || !DATA_HTML_HASHMAP.containsKey("验证码验证验证后继续Txt")) {
                              TXT.System_out_println("验证码匹配配置不正确...throw new Exception()");
                              throw new Exception();
                        }

                        String strPage = "";
                        String str1 = DATA_HTML_HASHMAP.get("验证码验证过于频繁Txt");
                        String str2 = DATA_HTML_HASHMAP.get("验证码验证服务异常Txt");
                        String str3 = DATA_HTML_HASHMAP.get("验证码验证验证通过Txt");
                        String str4 = DATA_HTML_HASHMAP.get("验证码验证验证后继续Txt");

                        tma = 0;
                        while (true) {

                              if (tma > WHILE_LOOP_TOP) {
                                        TXT.System_out_println("处理滑块验证码失败nSort = " + nSort + "...throw new Exception()");
                                        throw new Exception();
                              }

                              strPage = driver.getPageSource();
                              // 页面超时,子页面刷新浏览器
                              if ((strPage.contains(str1) || strPage.contains(str2)) && nSort > 0) {
                                        driver.navigate().refresh(); // 刷新子页面
                                        Thread.sleep(500);
                              }

                              // 页面超时,主页面刷新浏览器
                              if (strPage.contains(str2) && nSort == 0) {
                                        refreshMainPage(driver); // 主页面点击刷新按钮
                                        Thread.sleep(500);
                              }

                              // 判断是否绕过验证码
                              if (strPage.contains(str3) || !strPage.contains(str4)) {
                                        break;
                              }

                              // 下载图片
                              if (!downVerifyImg(driver, sBlockName, sBgName, nSort)) {
                                        TXT.System_out_println("下载验证码图片失败...throw new Exception()");
                                        throw new Exception();
                              }

                              // 给图片取名
                              nCurSort = 0;
                              if (DATA_VERIFY_HASHMAP.containsKey(nSort)) {
                                        nCurSort = DATA_VERIFY_HASHMAP.get(nSort);
                              }

                              TXT.System_out_println("OpenCV read1");
                              TXT.System_out_println(sVerifyFile + "/Block" + nSort + "_" + nCurSort + ".jpg");
                              // 对滑块进行处理
                              matSlideBlock = Imgcodecs.imread(sVerifyFile + "/Block" + nSort + "_" + nCurSort + ".jpg");
                              // 灰度化图片
                              TXT.System_out_println("OpenCV read1.1");
                              Imgproc.cvtColor(matSlideBlock, matSlideBlock, Imgproc.COLOR_BGR2GRAY);
                              // 去除周围黑边
                              for (int row = 0; row < matSlideBlock.height(); row++) {
                                        for (int col = 0; col < matSlideBlock.width(); col++) {
                                                if (matSlideBlock.get(row, col) == 0) {
                                                      matSlideBlock.put(row, col, 96);
                                                }
                                        }
                              }
                              // 二值化转黑白图
                              TXT.System_out_println("OpenCV read1.2");
                              Core.inRange(matSlideBlock, Scalar.all(96), Scalar.all(96), matSlideBlock);

                              TXT.System_out_println("OpenCV read2");
                              // 对背景图进行处理
                              matSlideBg = Imgcodecs.imread(sVerifyFile + "/Bg" + nSort + "_" + nCurSort + ".jpg");
                              // 灰度化图片
                              Imgproc.cvtColor(matSlideBg, matSlideBg, Imgproc.COLOR_BGR2GRAY);
                              // 二值化
                              Imgproc.threshold(matSlideBg, matSlideBg, 127, 255, Imgproc.THRESH_BINARY);

                              TXT.System_out_println("OpenCV read3");
                              // 保存处理后的图片
                              Imgcodecs.imwrite(sVerifyFile + "/Copy_Block" + nSort + "_" + nCurSort + ".jpg", matSlideBlock);
                              Imgcodecs.imwrite(sVerifyFile + "/Copy_Bg" + nSort + "_" + nCurSort + ".jpg", matSlideBg);

                              TXT.System_out_println("OpenCV read4");
                              // 计算位置
                              matResult = new Mat();
                              Imgproc.matchTemplate(matSlideBg, matSlideBlock, matResult, Imgproc.TM_CCOEFF_NORMED);
                              Point matchLocat = Core.minMaxLoc(matResult).maxLoc;
                              x = new Double(matchLocat.x).intValue();
                              y = new Double(matchLocat.y).intValue();
                              if (!DATA_VERIFY_ZOOM_HASHMAP.containsKey(nSort)) {
                                        TXT.System_out_println("没有存储缩放比例...throw new Exception()");
                                        throw new Exception();
                              }
                              x *= DATA_VERIFY_ZOOM_HASHMAP.get(nSort);
                              y *= DATA_VERIFY_ZOOM_HASHMAP.get(nSort);

                              // 拖动验证码准备验证
                              List<WebElement> dragElements = driver.findElements(By.className(sDragName));
                              actions = new Actions(driver);
                              tmb = 0;
                              while (dragElements.size() == 0) {

                                        if (tmb > WHILE_LOOP_NORMAL) {
                                                TXT.System_out_println("拖动控件元素未找到...throw new Exception()");
                                                throw new Exception();
                                        }

                                        Thread.sleep(100);
                                        dragElements = driver.findElements(By.className(sDragName));
                                        tmb++;
                              }

                              // 开始滑动
                              moveTrack = getMoveTrack(x);
                              actions.clickAndHold(dragElements.get(0)).perform();
                              for (Integer index : moveTrack) {
                                        actions.moveByOffset(index, 0).perform();
                              }
                              actions.release().perform();

                              Thread.sleep(500);
                              tma++;
                        }

                        bfinal = true;

                } catch (Exception e) {
                        bfinal = false;
                } finally {

                        if (!bfinal) {

                              TXT.System_out_println("handleVerifyCode...finally...bfinal = " + bfinal);
                        }

                        return bfinal;
                }
      }


      /*
         * Function(8) getMoveTrack(int)
         *
         * 描绘滑动轨迹
         */
      public static List<Integer> getMoveTrack(int dist) {

                List<Integer> track = new ArrayList();
                try {
                        Random rand = new Random();
                        int cur = 0; // 已经移动的距离
                        int r = 0; // 随机数
                        int move = 0; // 每次移动的距离
                        String str = "";
                        while (true) {
                              r = rand.nextInt(20);
                              move += r;

                              if (r > 18) {
                                        move = -move / 2;
                              }

                              if ((cur + move) < dist) {
                                        track.add(move);
                              } else {
                                        track.add(dist - cur);
                                        str += dist - cur;
                                        break;
                              }

                              cur += move;
                              str += move + ",";
                        }

                        TXT.System_out_println("计算滑动轨迹完毕,str = " + str + "...throw new Exception()");

                } catch (Exception e) {

                } finally {
                        return track;
                }
      }

ttyy008 发表于 2022-3-5 22:29

OpenCv即可,
c#版本:OpenCvSharp,https://www.52pojie.cn/thread-1464193-1-1.html
python处理:https://docs.opencv.org/4.x/d6/d00/tutorial_py_root.html

tsu.xxw 发表于 2022-3-5 22:37

zhiwoda 发表于 2022-3-5 22:18
原理:先把两张图片下载下来,然后用opencv灰度化,计算滑块位置,然后以非匀速拖过去


谢谢指导

tsu.xxw 发表于 2022-3-5 22:37

ttyy008 发表于 2022-3-5 22:29
OpenCv即可,
c#版本:OpenCvSharp,https://www.52pojie.cn/thread-1464193-1-1.html
python处理:https ...

谢谢,我去学习下

风在前,无惧 发表于 2022-3-5 22:39

个人建议,如果爬取的网站有各种类型的验证码,没有时间去搞验证想直接拿来用,不如试试打码平台,交给他们来做哈哈哈,有免费的额度

tsu.xxw 发表于 2022-3-5 22:40

风在前,无惧 发表于 2022-3-5 22:39
个人建议,如果爬取的网站有各种类型的验证码,没有时间去搞验证想直接拿来用,不如试试打码平台,交给他们 ...

是的,目前只是在学习python技术,所以想自己搞下

黑猫的猫 发表于 2022-3-5 23:18

zhiwoda 发表于 2022-3-5 22:18
原理:先把两张图片下载下来,然后用opencv灰度化,计算滑块位置,然后以非匀速拖过去,录了一个GIF可以看下 ...

{:1_893:}大佬哇,学习了

意决于心 发表于 2022-3-6 02:15

你好,能问一下什么平台有免费额度吗,一天多少次免费额度呢?

laos 发表于 2022-3-6 09:27

滑块的缺口位置识别向来是比较简单的一般难的是去分析它的轨迹算法
页: [1] 2
查看完整版本: python怎样过滑块?