puppeteer 微信群二维码采集

threeperson
发布于 2025-07-18 / 2 阅读
0
0

puppeteer 微信群二维码采集

先看下采集效果,录屏有些模糊,凑合看吧。

给出关键代码片段,完整代码请联系站长

主要引入的依赖

const puppeteer = require('puppeteer');
const fs = require('fs-extra');
const path = require('path');
let fetch;

const saveDir = 'C:/Users/40650/Desktop/qrcode';
const infoTxt = 'qrcode_info.txt';


下载函数实现

async function downloadImage(url) {


    // 在 isWeixin
    await fs.ensureDir(saveDir);
    let ext = '.jpg';
    if (url.includes('.png')) ext = '.png';
    else if (url.includes('.webp')) ext = '.webp';
    const filename = `img_${Date.now()}_${Math.floor(Math.random() * 9000 + 1000)}${ext}`;
    const filePath = path.join(saveDir, filename);
    const headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Accept': 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Referer': 'https://www.douyin.com/'
    };
    try {
        const res = await fetch(url, { headers });
        if (res.status === 200) {
            const arrayBuffer = await res.arrayBuffer();
            const buffer = Buffer.from(arrayBuffer);
            console.log('准备识别图片:', url, 'buffer长度:', buffer.length);
            // 识别二维码
            const isQR = await isWeixinQRCode(buffer);
            if (!isQR) {
                console.log('❌ 非微信二维码图片,跳过保存');

                return null;
            }
            await fs.writeFile(filePath, buffer);
            console.log('✅ 图片已保存:', filePath);
            return filePath;
        } else {
            console.log('❌ 下载失败,状态码:', res.status);
        }
    } catch (e) {
        console.log('❌ 下载出错:', e);
    }
    return null;
}

二维码图片识别(色值转换,增强,提高采集准确率)

// 判断图片 buffer 是否为微信二维码(动态 import 兼容 ESM)
// 使用 sharp + @zxing/library 实现 buffer 二维码识别
async function isWeixinQRCode(buffer) {
    console.log('开始识别二维码...');
    const sharp = (await import('sharp')).default || (await import('sharp'));
    const ZXingModule = await import('@zxing/library');
    const { MultiFormatReader, BarcodeFormat, RGBLuminanceSource, BinaryBitmap, HybridBinarizer, DecodeHintType } = ZXingModule;
    // 多种预处理:原图、灰度、反色、灰度反色
    const preprocessList = [
        async img => img,
        async img => img.clone().greyscale(),
        async img => img.clone().negate(),
        async img => img.clone().greyscale().negate(),
    ];
    try {
        for (const preprocess of preprocessList) {
            let image = sharp(buffer);
            image = await preprocess(image);
            const { width, height } = await image.metadata();
            const raw = await image.ensureAlpha().raw().toBuffer();
            const luminances = new Uint8ClampedArray(width * height);
            for (let i = 0; i < width * height; i++) {
                // 灰度 = R*0.299 + G*0.587 + B*0.114
                const r = raw[i * 4];
                const g = raw[i * 4 + 1];
                const b = raw[i * 4 + 2];
                luminances[i] = 0.299 * r + 0.587 * g + 0.114 * b;
            }
            const source = new RGBLuminanceSource(luminances, width, height);
            const bitmap = new BinaryBitmap(new HybridBinarizer(source));
            const reader = new MultiFormatReader();
            const hints = new Map();
            hints.set(DecodeHintType.POSSIBLE_FORMATS, [BarcodeFormat.QR_CODE]);
            reader.setHints(hints);
            try {
                const result = reader.decode(bitmap);
                const qrText = result.getText().toLowerCase();
                console.log('✅ 检测图片内容:', qrText);
                if (qrText.includes('weixin') || qrText.includes('wx') || qrText.includes('wechat')) {
                    console.log('✅ 检测到微信二维码:', qrText);
                    return true;
                } else {
                    console.log('❌ 检测到二维码,但不是微信二维码:', qrText);
                    return false;
                }
            } catch (err) {
                // 本次预处理未识别,继续尝试下一个
            }
        }
        console.log('❌ ZXing 所有预处理均未识别二维码');
        return false;
    } catch (e) {
        console.log('❌ isWeixinQRCode 整体异常:', e);
        return false;
    }
}


评论