准备工作
安装必要的工具和库
首先,确保你已经安装了Node.js环境。接下来,我们需要安装Puppeteer和OpenCV的Node.js绑定。
安装Node.js包
在项目中添加以下NPM包:
puppeteer
opencv4nodejs
你可以通过以下命令来安装这些包:
sh
npm install puppeteer
npm install opencv4nodejs
验证码页面
验证码页面地址:https://dun.163.com/trial/jigsaw
代码实现
1. 初始化Puppeteer
我们首先启动Puppeteer并导航到验证码页面。
javascript
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://dun.163.com/trial/jigsaw');
await page.waitForTimeout(3000); // 等待页面加载
// 后续的验证码处理代码将放在这里
await browser.close();
})();
2. 获取验证码图片
获取验证码图片并保存到本地,以便使用OpenCV进行图像处理。
javascript
const fs = require('fs');
const path = require('path');
const axios = require('axios');
async function downloadImage(url, filepath) {
const response = await axios({
url,
responseType: 'stream',
});
return new Promise((resolve, reject) => {
response.data.pipe(fs.createWriteStream(filepath))
.on('finish', () => resolve())
.on('error', e => reject(e));
});
}
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://dun.163.com/trial/jigsaw');
await page.waitForTimeout(3000); // 等待页面加载
const bgImageElement = await page.$('.yidun_bg-img');
const puzzleImageElement = await page.$('.yidun_jigsaw');
const bgSrc = await page.evaluate(el => el.src, bgImageElement);
const puzzleSrc = await page.evaluate(el => el.src, puzzleImageElement);
await downloadImage(bgSrc, path.resolve(__dirname, 'bg.png'));
await downloadImage(puzzleSrc, path.resolve(__dirname, 'puzzle.png'));
// 后续的验证码处理代码将放在这里
await browser.close();
})();
3. 使用OpenCV匹配图像
使用OpenCV找到拼图缺口的位置。
javascript
const cv = require('opencv4nodejs');
function getSlideDistance() {
const bgImage = cv.imread(path.resolve(__dirname, 'bg.png'));
const puzzleImage = cv.imread(path.resolve(__dirname, 'puzzle.png'));
const grayBg = bgImage.cvtColor(cv.COLOR_BGR2GRAY);
const grayPuzzle = puzzleImage.cvtColor(cv.COLOR_BGR2GRAY);
const result = grayBg.matchTemplate(grayPuzzle, cv.TM_CCOEFF_NORMED);
const minMax = result.minMaxLoc();
const { maxLoc: { x } } = minMax;
return x;
}
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://dun.163.com/trial/jigsaw');
await page.waitForTimeout(3000); // 等待页面加载
const bgImageElement = await page.$('.yidun_bg-img');
const puzzleImageElement = await page.$('.yidun_jigsaw');
const bgSrc = await page.evaluate(el => el.src, bgImageElement);
const puzzleSrc = await page.evaluate(el => el.src, puzzleImageElement);
await downloadImage(bgSrc, path.resolve(__dirname, 'bg.png'));
await downloadImage(puzzleSrc, path.resolve(__dirname, 'puzzle.png'));
const distance = getSlideDistance();
console.log(`Slide distance: ${distance}`);
// 后续的验证码处理代码将放在这里
await browser.close();
})();
4. 模拟滑动行为
模拟人类滑动行为,以避免被检测为机器人。
javascript
async function slidePuzzle(page, distance) {
const slider = await page.$('.yidun_slider');
const boundingBox = await slider.boundingBox();
const startX = boundingBox.x + boundingBox.width / 2;
const startY = boundingBox.y + boundingBox.height / 2;
await page.mouse.move(startX, startY);
await page.mouse.down();
const steps = 30;
const moveX = distance / steps;
const randomDelay = () => Math.floor(Math.random() * 100) + 100;
for (let i = 0; i < steps; i++) {
await page.mouse.move(startX + i * moveX, startY, { steps: 10 });
await page.waitForTimeout(randomDelay());
}
await page.mouse.up();
}
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://dun.163.com/trial/jigsaw');
await page.waitForTimeout(3000); // 等待页面加载
const bgImageElement = await page.$('.yidun_bg-img');
const puzzleImageElement = await page.$('.yidun_jigsaw');
const bgSrc = await page.evaluate(el => el.src, bgImageElement);
const puzzleSrc = await page.evaluate(el => el.src, puzzleImageElement);
await downloadImage(bgSrc, path.resolve(__dirname, 'bg.png'));
await downloadImage(puzzleSrc, path.resolve(__dirname, 'puzzle.png'));
const distance = getSlideDistance();
console.log(`Slide distance: ${distance}`);
await slidePuzzle(page, distance);
await page.waitForTimeout(5000); // 保持浏览器打开状态以查看结果
await browser.close();
})();
更多内容联系q1436423940