本地化使用微信截图功能,你可以这样做,NODEJS

641 阅读3分钟

本地微信OCR的js版本来源

发现有 大神 逆向微信自带的OCR功能。最后看了半天用到了另一个 大神 帮你简化后的ddl,其实这位大佬用到了另一位 大佬 项目里src里面的c#编译出来的函数,里面的wechat_ocr函数可以用来控制微信自带的mmmojo.dll和wechatOrc.exe。

而mmmojo.dll和wechatOrc.exe是用来调用微信OCR最重要的两个文件,PS:微信自带的。

废话不多说,直接展示代码,不过在展示代码之前,我们需要配置一些基本的环境,特别是里面的node-gyp,它允许使用C++/C等底层语言编写的模块在Node.js环境中运行,但是安装它有点费劲,下面是我的配置 (可能是这个项目我做下来其中最麻烦的之一)

image.png

关键的一步就是可以安装好ffi-napi就好了,ffi-napi可以加载并使用本地的动态链接库或共享对象,实现与现有的C/C++代码的集成‌。

进入代码阶段

在上述环境搞好的情况下,本身其实js代码很简单的,就是加载好大佬给封装好的wcocr.ddl,确定自己mmmojo.ddl这个文件的所在路径和wechatOrc.exe的路径就好了。如下:

const wechatDir = "D:\\normalLife\\WeChat\\[3.9.12.29]";
const ocrExe = "C:\\Users\\98178\\AppData\\Roaming\\Tencent\\WeChat\\XPlugin\\Plugins\\WeChatOCR\\7079\\extracted\\WeChatOCR.exe";

完整代码如下:

const ffi = require('ffi-napi');
const ref = require('ref-napi');
const wchar = require('ref-wchar-napi'); 
const { promisify } = require('util');
const path = require('path');

// Define the DLL interface with absolute path
const WechatOCR = ffi.Library(path.join(__dirname, 'wcocr.dll'), {
    'wechat_ocr': ['bool', [
        wchar.string,  // ocrExeWStr
        wchar.string,  // wechatDirWStr
        'string',      // imgFn
        'pointer'      // callback
    ]],
});
async function performOCR(ocrExePath, wechatDirPath, imagePath) {
    console.log("Starting OCR process...");
    return new Promise((resolve, reject) => {
        try {
            // 验证DLL是否正确加载
            if (!WechatOCR || !WechatOCR.wechat_ocr) {
                throw new Error("DLL not properly loaded");
            }

            // 检查文件路径是否都是字符串类型
            console.log("Checking parameters types:", {
                ocrExePath: typeof ocrExePath,
                wechatDirPath: typeof wechatDirPath,
                imagePath: typeof imagePath
            });

            const callback = ffi.Callback('void', ['string'], (result) => {
                if (!result) {
                    reject(new Error("OCR result is empty"));
                    return;
                }
                resolve(result);
            });

            try {
                console.log("Attempting to call DLL function...");
                const success = WechatOCR.wechat_ocr(
                    ocrExePath,
                    wechatDirPath,
                    imagePath,
                    callback
                );
                console.log("OCR function call returned:", success);
                
                if (!success) {
                    // 更详细的错误信息
                    const error = new Error("OCR initialization failed");
                    error.details = {
                        ocrExePath,
                        wechatDirPath,
                        imagePath
                    };
                    reject(error);
                }
            } catch (dllError) {
                console.error("DLL call failed with error:", {
                    message: dllError.message,
                    code: dllError.code,
                    stack: dllError.stack
                });
                reject(dllError);
            }
        } catch (error) {
            console.error("Error in performOCR:", error);
            reject(error);
        }
    });
}

async function main() {
    try {
        console.log("OCR begin...");
        
        // 替换成你自己本地的
        const ocrExe = "C:\\Users\\98178\\AppData\\Roaming\\Tencent\\WeChat\\XPlugin\\Plugins\\WeChatOCR\\7079\\extracted\\WeChatOCR.exe";
        const wechatDir = "D:\\normalLife\\WeChat\\[3.9.12.29]";
        // 替换成你自己的图片路径或者直接用我的demo图片
        const testImage = "C:\\Users\\98178\\Pictures\\Screenshots\\屏幕截图 2024-11-10 203019.png";

        // Verify if files exist
        const fs = require('fs');
        [ocrExe, wechatDir, testImage].forEach(path => {
            if (!fs.existsSync(path)) {
                throw new Error(`Path does not exist: ${path}`);
            }
        });

        const result = await performOCR(ocrExe, wechatDir, testImage);
        // console.log("OCR result:", result);
        const {ocr_response} = JSON.parse(result);
        const combinedText = ocr_response
            .sort((a, b) => a.top - b.top)  // 按照 top 坐标排序,确保文本顺序从上到下
            .map(item => item.text)          // 提取所有的 text 字段
            .join('\n');                     // 用换行符连接所有文本
        
        console.log("Combined text:");
        console.log(combinedText);
        console.log("OCR end...");
    } catch (error) {
        console.error("Error in main:", error);
    }
}

// Run the main function
main().catch(console.error);
exports.performOCR = performOCR;
这里有一个点:

就是下面这段代码,我一开始ddl总是调用出现问题,说是初始化有问题,后来问了好久copilot才发现,是wcocr.dll里面的wechat_ocr的前两个入参是用unicode的格式,直接写string是不行的,后来搞了半天才发现,换了格式后,一下子就可以了。

const WechatOCR = ffi.Library(path.join(__dirname, 'wcocr.dll'), {
    'wechat_ocr': ['bool', [
        wchar.string,  // ocrExeWStr
        wchar.string,  // wechatDirWStr
        'string',      // imgFn
        'pointer'      // callback
    ]],
});

最后就是直接运行这个js,就可以把你的图片中的文字提取出来了,效果图如下:

556e6c0d5c83abc73799250273be5ea.png

可以看到效果还是非常不错的。

最后觉得有意思,希望可以获得你的赞,项目地址