Text Captсha через node.js

fasawer

Новичок
Регистрация
19.11.2025
Сообщения
17
Благодарностей
15
Баллы
3
Всем доброго времени суток
рассмотрим тему текстовой каптчи
сделал мини решение для себя распознание текстовой кааптчи base64 png через node.js

решение для многопоточного варианта использования

ну начнем



Скачайте LTS-версию с nodejs.org
При установке оставьте галочку Add to PATH

Открываем командную строку
и выполняем команды

проверка что все гуд
node -v
npm -v

Если показывает версии (например v20.x.x и 10.x.x) то у вас все топчик


следующие команды
БУДТЕ ВНИМАТЕЛЬНЫ КОМАНДЫ ВЫПОЛНЯЕМ ПО 1 ПО ОЧЕРЕДИ


Создайте папку (например, на Рабочем столе)
cd %USERPROFILE%\Desktop
mkdir ocr-windows
cd ocr-windows

Инициализируйте проект и установите библиотеку
npm init -y
npm install tesseract.js

после всего установленного нами


один код


C#:
try
{
    project.SendInfoToLog("--- [OCR] Начало выполнения ---", true);

    string base64Image = project.Variables["Base64Image"].Value;
    if (string.IsNullOrEmpty(base64Image))
    {
        project.SendInfoToLog("Ошибка: Base64Image пуст", true);
        project.Variables["result_txt"].Value = "";
        return "error";
    }
    project.SendInfoToLog("Base64 получен, длина: " + base64Image.Length, true);

    string userPath = System.Environment.ExpandEnvironmentVariables("%USERPROFILE%");
    string workDir = System.IO.Path.Combine(userPath, "Desktop", "ocr-windows");
    if (!System.IO.Directory.Exists(workDir)) System.IO.Directory.CreateDirectory(workDir);

    string uniqueId = System.Guid.NewGuid().ToString("N");
    string jsFileName = "ocr_" + uniqueId + ".js";
    string resultFileName = "ocr_" + uniqueId + ".txt";
    string jsFilePath = System.IO.Path.Combine(workDir, jsFileName);
    string resultFilePath = System.IO.Path.Combine(workDir, resultFileName);

    project.SendInfoToLog("Уникальные имена: " + jsFileName + " / " + resultFileName, true);

    string safeBase64 = base64Image.Replace("\\", "\\\\").Replace("\"", "\\\"");

    // === JS КОД ===
    string jsCode = "const Tesseract = require('tesseract.js');\n" +
        "const fs = require('fs');\n" +
        "const base64Image = \"" + safeBase64 + "\";\n" +
        "const resultFile = \"" + resultFileName + "\";\n" +
        "(async () => {\n" +
        "    try {\n" +
        "        const cleanBase64 = base64Image.replace(/^.*;base64,/, '');\n" +
        "        const imageBuffer = Buffer.from(cleanBase64, 'base64');\n" +
        "        const worker = await Tesseract.createWorker('eng');\n" +
        "        await worker.setParameters({\n" +
        "            tessedit_char_whitelist: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',\n" +
        "            tessedit_pageseg_mode: 6\n" +
        "        });\n" +
        "        const result = await worker.recognize(imageBuffer);\n" +
        "        await worker.terminate();\n" +
        "        fs.writeFileSync(resultFile, (result.data.text || '').trim());\n" +
        "    } catch (err) {\n" +
        "        fs.writeFileSync(resultFile, 'ERROR:' + err.message);\n" +
        "    }\n" +
        "})();";

    System.IO.File.WriteAllText(jsFilePath, jsCode);
    project.SendInfoToLog("JS создан: " + jsFilePath, true);

    // === ПОИСК NODE.EXE ===
    string nodePath = @"C:\Program Files\nodejs\node.exe";
    if (!System.IO.File.Exists(nodePath)) nodePath = @"C:\Program Files (x86)\nodejs\node.exe";
    if (!System.IO.File.Exists(nodePath)) nodePath = System.IO.Path.Combine(userPath, "AppData", "Roaming", "npm", "node.exe");

    if (!System.IO.File.Exists(nodePath))
    {
        project.SendInfoToLog("node.exe не найден!", true);
        return "error";
    }

    // === ЗАПУСК ===
    System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
    psi.FileName = nodePath;
    psi.Arguments = "\"" + jsFileName + "\"";
    psi.WorkingDirectory = workDir;
    psi.CreateNoWindow = true;
    psi.UseShellExecute = false;
    psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

    project.SendInfoToLog("Запуск Node.js...", true);

    using (System.Diagnostics.Process proc = System.Diagnostics.Process.Start(psi))
    {
        bool exited = proc.WaitForExit(60000);
        if (!exited) { proc.Kill(); project.SendInfoToLog("Таймаут", true); }
        // Дополнительная пауза, чтобы ОС освободила файловые дескрипторы
        System.Threading.Thread.Sleep(1000);
    }

    // === ЧТЕНИЕ РЕЗУЛЬТАТА ===
    if (System.IO.File.Exists(resultFilePath))
    {
        string rawResult = System.IO.File.ReadAllText(resultFilePath).Trim();
        project.SendInfoToLog("Результат: '" + rawResult + "'", true);

        if (rawResult.StartsWith("ERROR:"))
        {
            project.SendInfoToLog("JS Error: " + rawResult.Substring(6), true);
            project.Variables["result_txt"].Value = "";
        }
        else
        {
            project.Variables["result_txt"].Value = rawResult;
            project.SendInfoToLog("Записано в result_txt", true);
        }
    }
    else
    {
        project.SendInfoToLog("Файл результата НЕ создан!", true);
        project.Variables["result_txt"].Value = "";
    }

    // ===  УДАЛЕНИЕ ВРЕМЕННЫХ ФАЙЛОВ (с повторными попытками) ===
    DeleteWithRetry(jsFilePath, "JS файл");
    DeleteWithRetry(resultFilePath, "TXT файл");

    project.SendInfoToLog("--- [OCR] Завершено ---", true);
    return "success";
}
catch (Exception ex)
{
    project.SendInfoToLog("=== C# ERROR ===", true);
    project.SendInfoToLog("Message: " + ex.Message, true);
    project.Variables["result_txt"].Value = "";
    return "error";
}

// === ВСПОМОГАТЕЛЬНЫЙ МЕТОД: Удаление с повторами ===
void DeleteWithRetry(string filePath, string fileName)
{
    int attempts = 0;
    int maxAttempts = 5;
   
    while (attempts < maxAttempts)
    {
        try
        {
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
                project.SendInfoToLog("Удалён: " + fileName, true);
                return;
            }
            // Файл уже не существует — выходим
            return;
        }
        catch (Exception ex)
        {
            attempts++;
            if (attempts >= maxAttempts)
            {
                project.SendInfoToLog("Не удалось удалить " + fileName + ": " + ex.Message, false);
                return;
            }
            // Ждём и пробуем снова
            System.Threading.Thread.Sleep(200);
        }
    }
}


код сам сам создает и запускает js с уникальным именем после выполнения и получения результат удаляет файлы

что нам нужно для того чтобы разгадать текстовую каптчу в моем случае это такой вариант

пример каптчи изображение


нам всего лишь нужно получить

картинку в base64

и запустить наш код

для работы кода создаем 2 переменные
Base64Image - куда мы передаем base64
result_txt куда код положит содержимое результата



доработать под свои нужны думаю каждый сможет сам

пользуйтесь и автоматизируйтесь
 
  • Спасибо
Реакции: Sergodjan и Moonwalker

Moonwalker

Client
Регистрация
16.03.2016
Сообщения
1 944
Благодарностей
1 637
Баллы
113
А зачем Node.js, если для работы с Tesseract либа есть, просто добавляется в окружение и работает "из коробки". Помню, давно уже было, что с его помощью телефоны на Авито парсили (они там в картинках были), когда там еще телефоны показывались реальные.
 
  • Спасибо
Реакции: Sergodjan

fasawer

Новичок
Регистрация
19.11.2025
Сообщения
17
Благодарностей
15
Баллы
3
А зачем Node.js, если для работы с Tesseract либа есть, просто добавляется в окружение и работает "из коробки". Помню, давно уже было, что с его помощью телефоны на Авито парсили (они там в картинках были), когда там еще телефоны показывались реальные.
искать решения на форме дольше чем создать и под свои нужды
 
  • Спасибо
Реакции: Sergodjan

fasawer

Новичок
Регистрация
19.11.2025
Сообщения
17
Благодарностей
15
Баллы
3
А зачем Node.js, если для работы с Tesseract либа есть, просто добавляется в окружение и работает "из коробки". Помню, давно уже было, что с его помощью телефоны на Авито парсили (они там в картинках были), когда там еще телефоны показывались реальные.
ну и если больше раскрыть суть то это всего лишь часть так как я node.js работаю с содержимым iframe где мне нужно раскрыть документ чтобы так же получать base64 что не позволяют другие методы
ну икаждый ищет более легкие и удобные для себя решения )) никого не осуждаю но комент по делу дал
 
  • Спасибо
Реакции: Sergodjan

Moonwalker

Client
Регистрация
16.03.2016
Сообщения
1 944
Благодарностей
1 637
Баллы
113
искать решения на форме дольше чем создать и под свои нужды
Ну так твое так же будут искать, получается ))) Но пусть будет, конечно, больше решений под разные нужды и привычки ))
 
  • Спасибо
Реакции: Sergodjan

Moonwalker

Client
Регистрация
16.03.2016
Сообщения
1 944
Благодарностей
1 637
Баллы
113
Кстати, мало ли, кому еще пригодится, пусть будет тут заодно (вдруг кто по поиску найдет тему).

Там два варианта сниппета:
1. Обрабатывает всю фотку
2. Обрабатывает определенную область на фото (задается координатами в сниппете).

Папки внутри архива кладем в свою Зенку.
1. Папку "tessdata" кладем в ...ZennoPoster Pro V7\<Ваша версия>\Progs....
Соответственно, так и кладем, отдельная папка появится
2. Из второй папки все файлики традиционно кладем в ExternalAssemblies

ps. Насколько помню, может быть проблема несовместимости .dll с системой, тогда надо просто скачать подходящую.
 

Вложения

  • Спасибо
Реакции: one и Sergodjan

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)