基于nodejs+selenium自动过滑动验证码的QQ刷赞
引子
不知道大家是否还记得之前让我刷赞的小朋友,自从他回到学校后,可能是由于学业太忙,把我们组成刷赞团队的事情忘记了,只是每天早上给我发信息帮他刷赞,迟迟没有新的用户,刷赞就没有量产的动力,我怠慢了几天没给他刷,他就不再理我了,我觉得是中了他的圈套,他只是嘴上说说要发展团队,其实只是贪恋我每天给他刷几万个赞。
效果
selnium过滑动验证码
代码
const webdriver = require('selenium-webdriver')
const firefox = require('selenium-webdriver/firefox');
const fs = require('fs')
const getPixels = require("get-pixels")
const ndarray = require("ndarray")!async function(){// 新建一个 firefox 的 driver 实例var options = new firefox.Options().setProfile('C:/Users/2bt/AppData/Roaming/Mozilla/Firefox/Profiles/m1mwcwm8.default')var driver = await new webdriver.Builder().forBrowser('firefox').setFirefoxOptions(options).build()console.log('开始模拟操作,命令提示符跳动代表着等待网页过程,默认都是10秒。如果网络较差,可能导致错误。')console.log('———————————————————————————————————————————————————————————————————————————————')main();async function main(){var distance = 0, dragX = 0 ,bgX =0 ,errX=0;// 访问极验demo页
await driver.get('http://www.jg520.com/?fid=1&tid=2095')var searchBox = driver.wait(webdriver.until.elementLocated(webdriver.By.id('inputvalue')), 10000)searchBox.sendKeys('809101180');
await driver.sleep(500)
console.log('填写QQ号')var btn = await driver.wait(webdriver.until.elementLocated(webdriver.By.id('submit_buy')), 10000)await driver.sleep(5000)await btn.click();
console.log('点击免费领取,等待验证码')try{
await driver.wait(webdriver.until.alertIsPresent(),5000);
let alert = await driver.switchTo().alert();
let alertText = await alert.getText();
if(alertText) console.log('每天限领一次,已领取,结束进程。')
await alert.accept();
return 0;
}catch(err){}btn = await driver.wait(webdriver.until.elementLocated(webdriver.By.css('.geetest_radar_tip')), 10000)
await btn.click();
await driver.sleep(3000)//找到验证码背景图元素, 是一个 canvas
const bgCanvas = await driver.wait(webdriver.until.elementLocated(webdriver.By.css('.geetest_window')), 30000)//1 截取bg图片
await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 1;document.querySelector(".geetest_canvas_slice").style.opacity = 0;')
const bgPng = await bgCanvas.takeScreenshot()
//取消隐藏
await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 1;document.querySelector(".geetest_canvas_slice").style.opacity = 1')getPixels('data:image/png;base64,'+bgPng,function(err, pixels) {if(err) {console.log("读取背景缺口位置错误")return}bgX = getBoundary(pixels,getGrey(pixels)/10*3)//console.log('读取背景缺口边界X坐标: ',bgX);
})// 获取拼图滑块按钮const button = await driver.wait(webdriver.until.elementLocated(webdriver.By.css('.geetest_slider_button')), 30000)// 初始化 actionlet actions = driver.actions({async: true})console.log('开始计算拖动位置')await driver.sleep(3000)// 把鼠标移动到滑块上, 然后点击await actions.move({origin: button,duration: 1000}).pause(100).press().move({origin: button,x: 1,duration: 10}).pause(300).perform()//截取slice图片,用于计算拖动后产生的随机位移await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 0;document.querySelector(".geetest_canvas_slice").style.opacity = 1;')const slice = await bgCanvas.takeScreenshot()//取消隐藏await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 1;document.querySelector(".geetest_canvas_slice").style.opacity = 1')getPixels('data:image/png;base64,'+slice.toString(),function(err, pixels) {if(err) {console.log("读取初始位置错误")return}dragX = getBoundary(pixels,360)})await driver.sleep(500)distance = bgX - dragX;var arr = getTrack(distance*0.8+20)//乘以0.8是因为计算出的值是以截取的canvas为基础的,真实拖动的距离需要乘以5:4这个比值console.log('开始拖动滑块,需要滑动的距离: ',distance*0.8+20)var backArr = [-4,-5,-6,-4,-2,-1]await moveTrack(arr,backArr)//4 再次截取slice图片,看看那里出错了await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 0;document.querySelector(".geetest_canvas_slice").style.opacity = 1;')const err = await bgCanvas.takeScreenshot()//取消隐藏await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 1;document.querySelector(".geetest_canvas_slice").style.opacity = 1')getPixels('data:image/png;base64,'+err,function(err, pixels) {if(err){console.log('获取最终位置错误')return}errX = getBoundary(pixels,360)console.log('完成移动到: ',errX,',错位: ',(errX - bgX)*0.8);})await driver.sleep(3000)const successTip = driver.wait(webdriver.until.elementLocated(webdriver.By.id('layui-layer10'),10000)).getText()if(successTip === '领取成功,等待到账,请收藏本站网址每天领福利,好东西一定要分享给好友哦!'){console.log('成功~')}else{console.log('失败~重新操作')await driver.sleep(3000) main()}}async function moveTrack(arr,backArr){let actions = driver.actions({bridge: true})for(i=0;i<arr.length;i++){var random = Math.floor(Math.random()*200+30)await actions.move({origin: webdriver.Origin.POINTER,x:arr[i],duration:random})}await actions.pause(100)for(i=0;i<backArr.length;i++){var random = Math.floor(Math.random()*200+30)await actions.move({origin: webdriver.Origin.POINTER,x:backArr[i],duration:random})}await actions.release().perform()
}async function move(distance){await driver.sleep(1000)let actions = driver.actions({bridge: true})await actions.move({origin: webdriver.Origin.POINTER,x:distance,duration:1000}).release().perform()console.log("滑动距离: ",distance)
}async function getStep(){//截取slice图片,用于计算拖动后产生的随机位移await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 0;document.querySelector(".geetest_canvas_slice").style.opacity = 1;')const slice = await bgCanvas.takeScreenshot()//取消隐藏await driver.executeScript('document.querySelector(".geetest_canvas_bg").style.opacity = 1;document.querySelector(".geetest_canvas_slice").style.opacity = 1')getPixels('data:image/png;base64,'+slice.toString(),function(err, pixels) {if(err) {console.log("读取初始位置错误")return}dragX = getBoundary(pixels,360)console.log('getStep函数返回:' ,dragX)})
}//取模拟拖动滑块的数据
//用等差数列代替了匀加速运动
//因为匀加速运动取得的小数经过四舍五入会出现不精确,导致拖动的距离出差错
function getTrack(distance){var track = [],d=2,n=0,s=0,S=0while(S<distance){s=1+n;n=n+d;S+=s;track.push(s)}var diff = (S - distance);track.splice(-1,1,Math.round(Number(track.slice(-1))-diff))return track;
}//getBoundary查找边界函数。
//参数
//pixels是get-pixel库获取的内容
//level是灰度,用来与一个像素点rgb三个值加起来的数比较,用于确定该点的黑色程度,level越小表示越黑。
function getBoundary(pixels, level){var lastY=0, count=0;for(var i=0; i < pixels.shape[0]; i++) {for(var j=0; j < pixels.shape[1]; j++) {var rgb = pixels.get(i,j,0) + pixels.get(i,j,1) + pixels.get(i,j,2)if(rgb < level && lastY+1 == j) {count++;//console.log(rgb, i,j ,count);}else count = 0;lastY = j;if(count > 6) return i;
}
}return 0;
}//获取灰度值
function getGrey(pixels){var rgb = 0;for(var i=0; i < pixels.shape[0]; i++) {for(var j=0; j < pixels.shape[1]; j++) {rgb += pixels.get(i,j,0) + pixels.get(i,j,1) + pixels.get(i,j,2)}}return Math.floor(rgb/pixels.shape[0]/pixels.shape[1])
}}()
使用方法
好像没啥特殊的,直接node就可以。
需要用npm
安装get-pixels
,ndarray
这两个包,用来识别图像的。
我用的是firefox,如果用chrocme或safari,需要自己去替换引用和下载驱动。
周末看了点node教程,讲node适用于任务调度,强项不是计算,怪不得网上的验证码代码大多都是python写的,而且遇到问题nodejs+selenium相关的答案较少,官网的文档又比较简单,废了好大的劲。
基于nodejs+selenium自动过滑动验证码的QQ刷赞相关推荐
- python+selenium+chrome 做滑动验证码 会被浏览器检测到使用的自动软件导致滑动验证失败
python+selenium+chrome 做滑动验证码 会被浏览器检测到使用的自动软件导致滑动验证失败 解决方法:代码中添加: import time from selenium import w ...
- selenium篇之滑动验证码
一.介绍 现在出现了一种通过用户鼠标移动滑块来填补有缺口图片的验证码,我们叫做滑动验证码.它的原理很简单,首先生成一张图片,然后随机挖去一块,在页面展示被挖去部分的图片,再通过js获取用户滑动距离,以 ...
- selenium+opencv干掉滑动验证码
我们在用自动化测试来做爬虫的时候,总是会遇见很多的验证码,其中的滑块拼接验证就是其中一种:selenium是一个自动化测试库,opencv是计算机视觉库,我们可以用这两个库来模仿人工滑动验证码,完成验 ...
- selenium爬虫|破解滑动验证码以极验为例
爬虫访问一些网站遇到滑动验证码解决方案 这里是用selenium做模拟,如果是requests可以封装这个登录方法来获取登录后的cookies也是可以用的. 1 思路 先讲思路,分析流程 我们输入账号 ...
- selenium破解bilbili滑动验证码
登陆b站的时候大家都会见到滑动验证码,打开开发者工具分析一下这里的验证码 1:首先需要鼠标触碰到滑动按钮才会显示出完整的验证码图片 2:点击按钮出现缺口图片 3:查看图片元素会(打开图片链接)发现完整 ...
- selenium登录 京东滑动验证码
京东的滑动验证码在页面上是没有原图的,所有我是用ps把他们拼成一个的. from selenium import webdriver from selenium.webdriver import Ac ...
- selenium自动登录QQ邮箱(附带滑动解锁)
问题分析:登录+滑动解锁 其实登录账号的部分本来很简单,用selenium打开QQ邮箱官网:https://mail.qq.com 然后切换frame输入帐号 和密码点击登录即可,但是部分账号,或者可 ...
- selenium自动化案例(二)滑动验证码破解
文章目录 写在前面 大致思路 Python实现 几个小坑 写在前面 最近学习了滑动验证的一个破解思路,是利用OpenCV的图形匹配算法进行对比验证,从而推算出滑块移动的距离,在实际应用中比较常见,我主 ...
- python selenium UI自动化解决验证码的4种方法
测试环境 windows7+ firefox50+ geckodriver # firefox浏览器驱动 python3 selenium3 selenium UI自动化解决验证码的4种方法:去掉验证 ...
最新文章
- nodejs web开发入门: Simple-TODO Nodejs 实现版
- 前端构建工具之争——Webpack vs Gulp 谁会被拍死在沙滩上
- python_day6 shutil模块
- jQuery kxbdMarquee 无缝滚动
- 两个不同网段的局域网如何互通_不同网段之间如何通信?
- 一次动态代理的填坑之旅
- 红帽linux lnmp搭建,RedHat/CentOs系统搭建lnmp环境
- AI芯片浮出新玩家OURS,来者何人?新晋图灵奖得主华人弟子谭章熹
- 算法:258. Add Digits 各位相加
- 纸鸢|物联网云平台小工具集合常见 MQTT 客户端比较
- 谈谈我对《ThoughtWorks文集》中多语言开发部分的看法
- Cordova插件之跳转第三方app
- Windows“控制面板”在哪?win10怎么打开控制面板(快捷方法)打开控制面板的多种方法都在这里
- 笔记本共享网络给台式机
- Rviz显示不出数据了之一文搞懂Qos
- 使用 Byzanz 录制 Gif 动画或 Ogv 视频
- ESP32开发2——新建项目
- android App中bug收集的工具类
- from scipy.misc import imread, imresize, imsave 报错的解决方法
- 从零学习Fluter(八):Flutter的四种运行模式--Debug、Release、Profile和test以及命名规范...
热门文章
- 打造吸睛运动耳机 Skullcandy推出“独立紫”限量套装
- 盘点十大能净化空气的植物
- 有哪些可以直接PS图片的在线工具呀
- iFIERO -- SkyNinja天猪之城 SpriteKit iOS游戏源码
- 一张图不用,纯CSS 做个生日贺卡
- a73*2+a53*2指的是什么_小鸡宝宝考考你 买空调时推销员经常提到的1匹2匹等指的是空调的|小鸡|宝宝-360GAME...
- 实战:云开发·实现奶茶店小程序(二)
- 一文讲清Python的7大学习路线(建议收藏)
- python格式化输出日期_1、Python 日期时间格式化输出
- Python:ffmpeg修改视频分辨率