前期准备

前往OCR文字识别_免费试用_图片转文字-百度AI开放平台 (baidu.com),申请文字识别并创建应用,虽然标准版可以调用的次数很多,但还是建议申请高精度版,我试了下普通版本识别准确度不太高

申请

创建应用

安装依赖

yarn add puppeteer 
yarn add baidu-aip-sdk 
yarn add download
//or npm
npm install puppeteer 
npm install baidu-aip-sdk 
npm install download

新建AipOcrClient

AipOcrClient是Optical Character Recognition的node客户端,为使用Optical Character Recognition的开发人员提供了一系列的交互方法。

用户可以参考如下代码新建一个AipOcrClient:

var AipOcrClient = require("baidu-aip-sdk").ocr;

// 设置APPID/AK/SK
var APP_ID = "你的 App ID";
var API_KEY = "你的 Api Key";
var SECRET_KEY = "你的 Secret Key";

// 新建一个对象,建议只保存一个对象调用服务接口
var client = new AipOcrClient(APP_ID, API_KEY, SECRET_KEY);

通用文字识别

用户向服务请求识别某张图中的所有文字。

var fs = require('fs');

var image = fs.readFileSync("assets/example.jpg").toString("base64");

// 调用通用文字识别, 图片参数为本地图片
client.generalBasic(image).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});

// 如果有可选参数
var options = {};
options["language_type"] = "CHN_ENG";
options["detect_direction"] = "true";
options["detect_language"] = "true";
options["probability"] = "true";

// 带参数调用通用文字识别, 图片参数为本地图片
client.generalBasic(image, options).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});;

var url = "https//www.x.com/sample.jpg";

// 调用通用文字识别, 图片参数为远程url图片
client.generalBasicUrl(url).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});

// 如果有可选参数
var options = {};
options["language_type"] = "CHN_ENG";
options["detect_direction"] = "true";
options["detect_language"] = "true";
options["probability"] = "true";

// 带参数调用通用文字识别, 图片参数为远程url图片
client.generalBasicUrl(url, options).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});;

通用文字识别 返回示例

{
"log_id": 2471272194,
"words_result_num": 2,
"words_result":
    [
        {"words": " TSINGTAO"},
        {"words": "青島睥酒"}
    ]
}

通用文字识别(高精度版)

用户向服务请求识别某张图中的所有文字,相对于通用文字识别该产品精度更高,但是识别耗时会稍长。

var fs = require('fs');

var image = fs.readFileSync("assets/example.jpg").toString("base64");

// 调用通用文字识别(高精度版)
client.accurateBasic(image).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});

// 如果有可选参数
var options = {};
options["detect_direction"] = "true";
options["probability"] = "true";

// 带参数调用通用文字识别(高精度版)
client.accurateBasic(image, options).then(function(result) {
    console.log(JSON.stringify(result));
}).catch(function(err) {
    // 如果发生网络错误
    console.log(err);
});;

使用puppeteer开始模拟签到过程

分析皇后的签到按钮,点击后弹出一个iframe,iframe地址为plugin_sign-in.php,因此实现的思路就是先打开浏览器把cookie先导入浏览器,访问这个地址即可。

直接开干

let opencdSign = async() => {
    let options = {
        args: [
            //是否使用代理,如果使用代理下面2行取消注释,并填写你自己的代理地址
            // '--proxy-server=127.0.0.1:10809',
            // '--proxy-bypass-list=<-loopback>',
            '--lang=en-US'
        ],
    }
    let browser = await puppeteer.launch(options);
    const page = await browser.newPage();
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1,
    });
    let cookieString = `填写你的皇后cookie`
    const addCookies = async(cookies_str, page, domain) => {
        let cookies = cookies_str.split(';').map(
            pair => {
                let name = pair.trim().slice(0, pair.trim().indexOf('='));
                let value = pair.trim().slice(pair.trim().indexOf('=') + 1);
                return { name, value, domain }
            });
        await Promise.all(cookies.map(pair => {
            // console.log(pair);
            return page.setCookie(pair)
        }))
    };
    await addCookies(cookieString, page, '皇后地址,不带https://')
    await page.goto('https://皇后地址/plugin_sign-in.php');

    let image = await page.$eval('#frmSignin > table > tbody > tr > td > img', el => el.src)
    console.log(image)
    // 调用通用文字识别, 图片参数为网络URL
    // client.generalBasicUr(image).then(async result => { //普通版
    // 坑爹的高精度不能直接使用网络图片,只能先下载下来
    let headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
    }
    const filePath = `${__dirname}/images`
    await download(imageUrl, filePath, {
        filename: 'orc.png',
        headers,
    }).then(() => {
        console.log(`Download Completed`)
        let image = fs.readFileSync(`${__dirname}/images/orc.png`).toString("base64");
        client.accurateBasic(image).then(async result => { //高精度版
            let imageOrc = JSON.stringify(result.words_result[0].words).replace(/[^0-9a-zA-z]/g,"")
            console.log(imageOrc)
            await page.focus('#imagestring')
            await page.keyboard.sendCharacter(imageOrc)
            await page.click('#ok')
            // await page.screenshot({ path: `${new Date().getTime()}opencd.png` });
            let signResult = await page.$eval('html', el => JSON.parse(el.innerText))
            console.log(signResult)
            let signinfo
            if (signResult.state == 'success') {
                signinfo = `签到成功,签到天数:${signResult.signindays},获得:${signResult.integral}`
            } else if (signResult.state == 'false' && signResult.msg) {
                signinfo = `${signResult.msg},尝试重新签到`
                opencdSign()
            } else {
                signinfo = `已经签到`
            }
            await browser.close();
        console.log(signinfo)
        }).catch(function(err) {
            // 如果发生网络错误
            console.log(err);
        });
    })
}

使用node-schedule实现定时签到

封装下方法
const schedule = require('node-schedule')
// date 参数

// 其他规则见 https://www.npmjs.com/package/node-schedule
// 规则参数讲解, 规则类似 Linux 下的 crontab ('*'代表通配符) 
//
// *  *  *  *  *  *
// ┬ ┬ ┬ ┬ ┬ ┬
// │ │ │ │ │ |
// │ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
// │ │ │ │ └───── month (1 - 12)
// │ │ │ └────────── day of month (1 - 31)
// │ │ └─────────────── hour (0 - 23)
// │ └──────────────────── minute (0 - 59)
// └───────────────────────── second (0 - 59, OPTIONAL)

// 1. 按固定时间触发
//
// 每分钟的第30秒触发: '30 * * * * *'
//
// 每小时的1分30秒触发 :'30 1 * * * *'
//
// 每天的凌晨1点1分30秒触发 :'30 1 1 * * *'
//
// 每月的1日1点1分30秒触发 :'30 1 1 1 * *'
//
// 每周1的1点1分30秒触发 :'30 1 1 * * 1'

// 2. 按时间差触发 (日/月/周同理)
//
// 每30分钟触发一次: '0 */30 * * * *'
//
// 每6小时触发一次: '0 0 */6 * * *'

function setSchedule(date, callback) {
    schedule.scheduleJob({tz: 'Asia/Shanghai', rule: date}, callback)
}

module.exports = {
    setSchedule
}
引入并调用
const schedule = require('./schedule/index');

schedule.setSchedule('0 0 * * * *', opencdSign())

写的比较混乱,完整代码有空了会优化下发布至github

最后修改:2022 年 09 月 21 日
如果觉得我的文章对你有用,请随意赞赏