Что такое Google Apps Script и его возможности
Google Apps Script (GAS) — это облачная платформа для разработки скриптов на основе JavaScript, позволяющая автоматизировать задачи и расширять функциональность сервисов Google Workspace (Sheets, Docs, Drive, Gmail и т.д.). Она предоставляет удобный способ интеграции различных сервисов Google и сторонних API.
Возможности GAS включают создание пользовательских функций для таблиц, автоматизацию документооборота, разработку веб-приложений, управление файлами на Google Drive, взаимодействие с внешними API и многое другое. Эта гибкость делает GAS мощным инструментом для разработчиков и продвинутых пользователей.
Обзор способов получения изображений из URL в Google Apps Script
Основным инструментом для взаимодействия с внешними ресурсами по URL в Google Apps Script является сервис UrlFetchApp. Он позволяет отправлять HTTP-запросы, включая GET-запросы для получения данных по указанному URL. Для изображений это означает получение двоичных данных файла.
Полученные данные изображения обычно представляются в виде Blob (Binary Large Object). Этот объект содержит необработанные данные файла и информацию о его типе (MIME type). В дальнейшем Blob можно использовать для сохранения файла на Google Drive или вставки непосредственно в документы Google Docs или таблицы Google Sheets.
Необходимые библиотеки и разрешения
Для получения изображений из URL и их последующей обработки потребуются следующие сервисы Google Apps Script:
UrlFetchApp: Для выполнения HTTP-запросов к URL изображения.
DriveApp: (Опционально) Для сохранения изображения на Google Drive.
SpreadsheetApp: (Опционально) Для вставки изображения в Google Sheets.
DocumentApp: (Опционально) Для вставки изображения в Google Docs.
При первом запуске скрипта, использующего эти сервисы, Google запросит у пользователя авторизацию. Необходимо предоставить разрешение на доступ к внешним сервисам (urlfetch) и, при необходимости, разрешение на управление файлами на Google Drive, таблицами или документами.
Получение изображения из URL с использованием UrlFetchApp
Описание сервиса UrlFetchApp
UrlFetchApp — это встроенный сервис GAS, предоставляющий интерфейс для выполнения HTTP(S) запросов. Он позволяет получать содержимое веб-страниц, взаимодействовать с API и, что важно для нашей задачи, загружать файлы, включая изображения, по их URL.
Сервис поддерживает различные методы запросов (GET, POST, PUT, DELETE и т.д.), установку заголовков, обработку ответов и управление параметрами запроса, такими как таймауты и обработка ошибок.
Пример кода: Получение изображения по URL и преобразование в Blob
/**
* Получает изображение по указанному URL и возвращает его как Blob.
*
* @param {string} imageUrl URL изображения для загрузки.
* @return {GoogleAppsScript.Base.Blob | null} Blob-объект изображения или null в случае ошибки.
*/
function fetchImageAsBlob(imageUrl: string): GoogleAppsScript.Base.Blob | null {
try {
// Опции запроса (можно добавить заголовки, таймауты и т.д.)
const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
method: 'get',
muteHttpExceptions: true // Важно для обработки ошибок вручную
};
// Выполняем запрос
const response: GoogleAppsScript.URL_Fetch.HTTPResponse = UrlFetchApp.fetch(imageUrl, options);
const responseCode: number = response.getResponseCode();
// Проверяем статус ответа
if (responseCode === 200) {
const imageBlob: GoogleAppsScript.Base.Blob = response.getBlob();
// Логгирование типа контента для отладки
Logger.log(`Изображение успешно получено. Тип контента: ${imageBlob.getContentType()}, Размер: ${imageBlob.getBytes().length} байт`);
return imageBlob;
} else {
Logger.log(`Ошибка получения изображения. URL: ${imageUrl}, Код ответа: ${responseCode}, Сообщение: ${response.getContentText()}`);
return null;
}
} catch (error) {
// Обработка других ошибок (например, недоступность сервиса UrlFetchApp)
Logger.log(`Критическая ошибка при запросе к URL ${imageUrl}: ${error}`);
return null;
}
}
// Пример использования:
function testFetchImage() {
const sampleImageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png'; // Пример URL
const blob = fetchImageAsBlob(sampleImageUrl);
if (blob) {
Logger.log('Blob успешно получен.');
// Дальнейшие действия с blob (сохранение, вставка и т.д.)
} else {
Logger.log('Не удалось получить Blob.');
}
}Обработка ошибок при получении изображения (таймауты, неверные URL и т.д.)
При работе с внешними ресурсами важно предусмотреть возможные ошибки. UrlFetchApp.fetch может генерировать исключения или возвращать HTTP-ответы с кодами ошибок.
Неверный URL или ресурс не найден (404): response.getResponseCode() вернет код, отличный от 200. Необходимо проверять этот код.
Таймауты: Запрос может превысить максимальное время ожидания (по умолчанию 30 секунд, максимум 6 минут для платных аккаунтов). Можно настроить таймаут в опциях, но обработка ошибки потребует try...catch.
Проблемы с сетью или сервером: Могут возникать ошибки на уровне сети или сервер может быть временно недоступен (коды 5xx).
Ограничения доступа (403 Forbidden): Некоторые серверы могут блокировать запросы от скриптов Google.
Использование muteHttpExceptions: true в опциях запроса позволяет перехватывать HTTP-ошибки (коды 4xx, 5xx) без генерации исключения скриптом, проверяя response.getResponseCode().
Ограничения UrlFetchApp и способы их обхода
Сервис UrlFetchApp имеет квоты и ограничения:
Количество вызовов в день: Зависит от типа аккаунта (G Suite/Workspace или бесплатный Gmail).
Время выполнения запроса: Максимум 6 минут.
Размер ответа: Ограничен (обычно 50 МБ).
Общий трафик в день.
Если требуется обрабатывать большое количество изображений или работать с очень большими файлами, можно столкнуться с этими лимитами. Возможные обходные пути:
Оптимизация: Запрашивать изображения только при необходимости, кэшировать результаты (например, сохраняя их на Drive и используя ID файла вместо повторной загрузки).
Пакетная обработка: Группировать операции, использовать триггеры для распределения нагрузки во времени.
Сторонние сервисы: Для сложных задач можно использовать внешние API или платформы (например, Cloud Functions), вызываемые из GAS, которые могут иметь более гибкие лимиты.
Сохранение полученного изображения в Google Drive
Получение доступа к Google Drive с использованием DriveApp
Сервис DriveApp предоставляет интерфейс для взаимодействия с файлами и папками на Google Drive пользователя или общем диске. Он позволяет создавать, искать, изменять и удалять файлы и папки.
Для сохранения изображения, полученного как Blob с помощью UrlFetchApp, используется метод createFile(blob).
Пример кода: Сохранение Blob-объекта изображения в Google Drive
/**
* Сохраняет Blob-объект как файл в указанную папку Google Drive.
*
* @param {GoogleAppsScript.Base.Blob} imageBlob Blob-объект изображения.
* @param {string} fileName Имя файла для сохранения.
* @param {string} [folderId] ID папки для сохранения (опционально, по умолчанию - корневая папка).
* @return {GoogleAppsScript.Drive.File | null} Объект сохраненного файла или null в случае ошибки.
*/
function saveBlobToDrive(imageBlob: GoogleAppsScript.Base.Blob, fileName: string, folderId?: string): GoogleAppsScript.Drive.File | null {
try {
let targetFolder: GoogleAppsScript.Drive.Folder;
if (folderId) {
try {
targetFolder = DriveApp.getFolderById(folderId);
} catch (e) {
Logger.log(`Не удалось найти папку с ID: ${folderId}. Сохранение в корневую папку.`);
targetFolder = DriveApp.getRootFolder();
}
} else {
targetFolder = DriveApp.getRootFolder();
}
// Устанавливаем имя файла для Blob перед сохранением
const namedBlob = imageBlob.setName(fileName);
const file = targetFolder.createFile(namedBlob);
Logger.log(`Файл '${fileName}' успешно сохранен в папку '${targetFolder.getName()}'. ID файла: ${file.getId()}`);
return file;
} catch (error) {
Logger.log(`Ошибка сохранения файла '${fileName}' в Google Drive: ${error}`);
return null;
}
}
// Пример использования:
function testSaveImageToDrive() {
const sampleImageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
const blob = fetchImageAsBlob(sampleImageUrl);
if (blob) {
// Генерируем имя файла (например, на основе URL или текущей даты)
const timestamp = new Date().toISOString().replace(/[:.-]/g, '');
const filename = `image_${timestamp}.png`; // Пытаемся угадать расширение или берем из Content-Type
// Можно указать ID конкретной папки
// const targetFolderId = 'YOUR_FOLDER_ID';
// saveBlobToDrive(blob, filename, targetFolderId);
saveBlobToDrive(blob, filename);
}
}Управление именами файлов и папками
При сохранении важно правильно управлять именами файлов, чтобы избежать конфликтов и обеспечить удобную организацию.
Уникальные имена: Генерируйте уникальные имена, например, добавляя временную метку или хэш URL.
Расширение файла: Пытайтесь определить правильное расширение файла на основе MIME-типа (blob.getContentType()) или URL.
Структура папок: Используйте DriveApp.getFolderById() или DriveApp.createFolder() для организации файлов в определенных папках. Проверяйте существование папки перед использованием.
Обработка дубликатов: Перед созданием файла можно проверить, не существует ли уже файл с таким именем в целевой папке (folder.getFilesByName(fileName)), и решить, перезаписывать его или создавать новый с уникальным именем.
Использование полученного изображения в Google Sheets или Docs
Вставка изображения в Google Sheets: пример кода
Полученный Blob можно вставить непосредственно в ячейку Google Sheets.
/**
* Вставляет изображение (Blob) в указанную ячейку Google Sheets.
*
* @param {GoogleAppsScript.Base.BlobSource} imageBlobSource Blob или файл Drive с изображением.
* @param {string} sheetName Имя листа.
* @param {string} cellNotation Обозначение ячейки (например, 'A1').
* @param {number} [offsetX] Смещение по X внутри ячейки (опционально).
* @param {number} [offsetY] Смещение по Y внутри ячейки (опционально).
*/
function insertImageIntoSheet(imageBlobSource: GoogleAppsScript.Base.BlobSource, sheetName: string, cellNotation: string, offsetX: number = 0, offsetY: number = 0): void {
try {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName);
if (!sheet) {
Logger.log(`Лист с именем '${sheetName}' не найден.`);
return;
}
const cell = sheet.getRange(cellNotation);
// Удаляем предыдущее изображение в ячейке, если оно есть
sheet.getImages().forEach(img => {
if (img.getAnchorCell().getA1Notation() === cellNotation) {
img.remove();
}
});
// Вставляем новое изображение
const image = sheet.insertImage(imageBlobSource, cell.getColumn(), cell.getRow(), offsetX, offsetY);
Logger.log(`Изображение успешно вставлено в ячейку ${cellNotation} листа '${sheetName}'.`);
// Дополнительно: можно настроить размер изображения
// image.setWidth(100);
// image.setHeight(50);
} catch (error) {
Logger.log(`Ошибка вставки изображения в Google Sheets: ${error}`);
}
}
// Пример использования:
function testInsertImageIntoSheet() {
const sampleImageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
const blob = fetchImageAsBlob(sampleImageUrl);
if (blob) {
insertImageIntoSheet(blob, 'Лист1', 'C3'); // Вставить в ячейку C3 на Лист1
}
}Вставка изображения в Google Docs: пример кода
Аналогично, Blob можно вставить в Google Docs.
/**
* Вставляет изображение (Blob) в конец документа Google Docs.
*
* @param {GoogleAppsScript.Base.BlobSource} imageBlobSource Blob или файл Drive с изображением.
* @param {string} [documentId] ID документа (опционально, по умолчанию - активный документ).
*/
function insertImageIntoDoc(imageBlobSource: GoogleAppsScript.Base.BlobSource, documentId?: string): void {
try {
let doc: GoogleAppsScript.Document.Document;
if (documentId) {
doc = DocumentApp.openById(documentId);
} else {
doc = DocumentApp.getActiveDocument();
}
const body = doc.getBody();
// Вставляем изображение в конец документа
const image = body.appendImage(imageBlobSource);
Logger.log(`Изображение успешно вставлено в документ ID: ${doc.getId()}.`);
// Дополнительно: можно настроить размер изображения
// const width = image.getWidth();
// const height = image.getHeight();
// image.setWidth(width / 2).setHeight(height / 2); // Уменьшить в 2 раза
} catch (error) {
Logger.log(`Ошибка вставки изображения в Google Docs: ${error}`);
}
}
// Пример использования:
function testInsertImageIntoDoc() {
const sampleImageUrl = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
const blob = fetchImageAsBlob(sampleImageUrl);
if (blob) {
insertImageIntoDoc(blob); // Вставить в активный документ
// const targetDocId = 'YOUR_DOCUMENT_ID';
// insertImageIntoDoc(blob, targetDocId); // Вставить в документ по ID
}
}Настройка размеров и положения изображения
После вставки изображения как в Sheets (sheet.insertImage), так и в Docs (body.appendImage или paragraph.appendInlineImage), возвращается объект OverGridImage (Sheets) или InlineImage (Docs). Эти объекты предоставляют методы для управления размерами и, в некоторой степени, положением.
Google Sheets: OverGridImage позволяет установить смещение (offsetX, offsetY) при вставке. После вставки можно изменять ширину (setWidth) и высоту (setHeight). Изображение привязано к ячейке (getAnchorCell).
Google Docs: InlineImage позволяет изменять ширину (setWidth) и высоту (setHeight). Положение определяется местом вставки в тексте документа.
Заключение и оптимизация
Рекомендации по оптимизации скрипта для работы с изображениями
Кэширование: Если один и тот же URL изображения используется многократно, сохраните Blob на Google Drive и используйте DriveApp.getFileById(id).getBlob() вместо повторной загрузки через UrlFetchApp.
Асинхронность: Для массовой обработки рассмотрите возможность использования триггеров или разделения задачи на части, чтобы не превышать лимиты времени выполнения.
Обработка ошибок: Всегда включайте надежную обработку ошибок для UrlFetchApp и операций с файлами/документами.
Размер изображений: Если возможно, используйте URL изображений с оптимальным размером, чтобы уменьшить время загрузки и объем данных.
Очистка: Удаляйте временные или ненужные файлы изображений с Google Drive, если они больше не требуются.
Альтернативные подходы и библиотеки (если применимо)
В рамках стандартного Google Apps Script сервис UrlFetchApp является основным и наиболее прямым способом получения данных по URL, включая изображения. Для специфических задач, таких как обработка изображений (изменение размера до вставки, наложение водяных знаков), могут потребоваться более сложные решения:
Google Cloud Functions: Можно создать функцию в Google Cloud, которая будет обрабатывать изображение (используя библиотеки типа sharp или ImageMagick), а затем вызывать эту функцию из GAS через UrlFetchApp.
Сторонние API: Существуют API для обработки изображений, которые можно вызывать из GAS.
Возможные проблемы и их решения
Превышение квот UrlFetchApp: Распределяйте запросы во времени, используйте кэширование.
Блокировка запросов сервером: Некоторые сайты могут блокировать запросы от Google. Попробуйте добавить User-Agent в заголовки запроса, но это не всегда помогает.
Неверный MIME-тип: response.getBlob() может вернуть Blob с неправильным или неопределенным типом контента. Проверяйте blob.getContentType() и при необходимости корректируйте расширение файла.
Ошибки авторизации: Убедитесь, что скрипту предоставлены все необходимые разрешения.
Дополнительные ресурсы и ссылки
Для дальнейшего изучения рекомендуется обратиться к официальной документации Google Apps Script:
Документация по UrlFetchApp.
Документация по DriveApp.
Документация по SpreadsheetApp и DocumentApp.
Обзор квот и ограничений Google Apps Script.
Изучение примеров на форумах сообщества и Stack Overflow также может быть полезным для решения конкретных задач и нестандартных задач.