Извлечение текста из PDF-файлов с помощью Google Apps Script

В современном цифровом рабочем процессе извлечение текста из PDF-документов остаётся важнейшей задачей для обработки данных, анализа контента и поиска информации. В то время как оптическое распознавание символов (OCR) обычно используется для PDF-файлов на основе изображений, PDF-файлы на основе текста, содержащие встроенные текстовые слои, требуют иного подхода. В этом руководстве подробно рассматривается извлечение текста из PDF-файлов на основе текста с помощью Google Apps Script с упором на собственные методы преобразования без использования OCR.

Технические основы извлечения текста в формате PDF

Понимание слоев текста PDF

В текстовых PDF-файлах символы хранятся как отдельные элементы в структуре файла, в отличие от PDF-файлов на основе изображений, для распознавания текста в которых требуется OCR. В таких документах используются потоки содержимого PDF, содержащие такие операторы, как TJ (отображение текста с позиционированием) и Tj (отображение текста), для отображения глифов из встроенных шрифтов. Эта структурная особенность позволяет напрямую извлекать текст без анализа пикселей.

Спецификация PDF (ISO 32000) определяет два основных режима отображения текста:

  1. Текстовый режим: Управляет выбором шрифта и глифа.
  2. Графический режим: обрабатывает операции векторной графики.
    Извлечение текста направлено на перехват и интерпретацию этих операций в текстовом режиме.

Механизм преобразования Google Диска

При преобразовании PDF-файлов в Google Диске используются компоненты библиотеки Apache PDFBox для анализа потоков PDF-контента. При преобразовании с помощью API Диска:

  • Глифы шрифта сопоставляются с эквивалентами в Юникоде
  • Операторы позиционирования текста интерпретируются для восстановления макета
  • Метаданные и структура документа сохранены в формате Google Docs

Этот процесс происходит на уровне API без необходимости в распознавании текста при работе с текстовыми PDF-файлами, обеспечивая точность распознавания символов более 99% для правильно закодированных документов.

Методология внедрения

Процесс извлечения

Стандартный конвейер извлечения текста состоит из четырех этапов:

  1. Получение документов
    • Извлеките PDF-файл из URL-адреса или хранилища на диске
    • Проверка типа MIME (application/pdf)
    • Проверка заголовков файловой структуры
  2. Преобразование привода
    • Преобразование с помощью API в формат Google Docs
    • Анализ потока контента и извлечение текстового слоя
    • Создание временного документа на Диске пользователя
  3. Обработка текста
    • Доступ к преобразованному тексту документа
    • Извлечение необработанного текстового содержимого
    • Обработка специальных символов и кодировки
  4. Очистка ресурсов
    • Удаление временных документов
    • Управление использованием квот API

Полная реализация кода

function extractTextFromPDF(pdfUrl) {
	try {
		// Fetch PDF with timeout handling
		const blob = UrlFetchApp.fetch(pdfUrl, { muteHttpExceptions: true })
		.getBlob()
		.setContentTypeFromExtension();
		
		// Verify PDF MIME type
		if (blob.getContentType() !== 'application/pdf') {
			throw new Error('Invalid MIME type - not a PDF file');
		}
		
		// Configure Drive API request
		const resource = {
			title: blob.getName().replace(/.pdf$/i, '_CONVERTED'),
			mimeType: blob.getContentType(),
		};
		
		const options = {
			convert: true,
			supportsAllDrives: false,
			ocr: false, // Explicitly disable OCR
		};
		
		// Execute conversion
		const file = Drive.Files.insert(resource, blob, options);
		
		// Access converted document
		const doc = DocumentApp.openById(file.id);
		const fullText = doc.getBody().getText();
		
		// Cleanup temporary resources
		DriveApp.getFileById(file.id).setTrashed(true);
		return fullText;
	} catch (error) {
		console.error(`Extraction failed: ${error.message}`);
		throw error;
	}
}

Расширенные Рекомендации по внедрению

Оптимизация производительности

  1. Пакетная обработка
function batchProcessPDFs(folderId) {
	const folder = DriveApp.getFolderById(folderId);
	const files = folder.getFilesByType(MimeType.PDF);
	while (files.hasNext()) {
		const file = files.next();
		try {
			const text = extractTextFromPDF(file.getUrl());
			// Implement text processing logic
		} catch (e) {
			console.error(`Error processing ${file.getName()}: ${e}`);
		}
	}
}
  1. Управление памятью
  • Реализовать фрагментарную обработку для больших документов
  • Используйте промежуточные текстовые буферы
  • Использование частичных ответов Drive API

Шаблоны обработки ошибок

const ERROR_CODES = {
    INVALID_URL: 1001,
    MIME_TYPE_MISMATCH: 1002,
    DRIVE_API_FAILURE: 2001,
    DOCUMENT_ACCESS: 3001,
};

function handleError(error) {
    switch (error.message) {
        case 'Invalid PDF URL format':
            return { code: ERROR_CODES.INVALID_URL, message: error.message };
        case 'Invalid MIME type - not a PDF file':
            return { code: ERROR_CODES.MIME_TYPE_MISMATCH, message: error.message };
        default:
            return { code: ERROR_CODES.DRIVE_API_FAILURE, message: error.message };
    }
}

Проблемы и решения, связанные с конкретным форматом

Обработка сложных макетов

  1. Извлечение текста из нескольких столбцов
function parseColumns(text) {
    const columnThreshold = 40; // Character count threshold
    return text.split('\n').reduce((acc, line) => {
        if (line.length < columnThreshold && acc.currentColumn) {
            acc.columns.push(acc.currentColumn.join(' '));
            acc.currentColumn = [];
        }
        acc.currentColumn.push(line.trim());
        return acc;
    }, { columns: [], currentColumn: [] });
}
  1. Реконструкция таблицы
    Реализовать алгоритмы постобработки для обнаружения табличных структур с использованием:
  • Шаблоны пробелов
  • Регулярные выражения
  • Статистический анализ распределения символов

Проблемы с кодировкой и шрифтом

  • Реализовать обнаружение кодировки с помощью TextDecoder
  • Создание пользовательских карт шрифтов для PDF-файлов, отличных от Юникода
  • Обрабатывайте ZapfDingbats и символьные шрифты с помощью таблиц подстановки

Использование API и управление квотами

Квоты Drive API

OperationQuota UnitsDaily Limit
Files.insert1001,000
DocumentApp.openById5050,000
UrlFetchApp.fetch20100,000

Лучшие практики:

  • Реализовать экспоненциальный откат для ошибок API
  • Используйте пакетную обработку в нерабочее время
  • Кэширование часто используемых документов
const API_DELAY = 1000; // Base delay in milliseconds

function withRetry(fn, retries = 3) {
    return async function (...args) {
        let attempt = 0;
        while (attempt <= retries) {
            try {
                return await fn(...args);
            } catch (error) {
                if (error.message.includes('Quota')) {
                    Utilities.sleep(API_DELAY * Math.pow(2, attempt));
                    attempt++;
                } else {
                    throw error;
                }
            }
        }
    };
}

Добавить комментарий