Как создать расширение Google Chrome: захват изображений

Как создать расширение Google Chrome: захват изображений

2 декабря 2022 г.

Введение

Расширения Chrome – это небольшие программы, которые можно установить в веб-браузере Google Chrome, чтобы расширить его возможности. Обычно, чтобы установить расширение Chrome, пользователь должен открыть Интернет-магазин Chrome, найти нужное расширение и установить его оттуда.

В этой статье я покажу, как создать расширение Chrome с нуля. Расширение, которое мы сегодня создадим, будет использовать Chrome API для доступа к содержимому веб-страниц, открытых в веб-браузере, и извлечения из них различной информации. Используя эти API, вы можете не только читать контент с веб-страниц, но и записывать на них контент и взаимодействовать с этими страницами, например, автоматически нажимая кнопки или переходя по ссылкам. Эту функцию можно использовать для широкого круга задач автоматизации браузера, таких как удаление необходимой информации с веб-сайтов или автоматизация веб-серфинга, что может быть полезно для автоматизации тестирования пользовательского интерфейса.

В этой статье я проведу вас через процесс создания расширения с именем Image Grabber. Полученное расширение предоставит интерфейс для подключения к веб-сайту, чтения всех изображений с него, захвата их абсолютных URL-адресов и копирования этих URL-адресов в буфер обмена. В ходе этого процесса вы узнаете об основных частях расширения Google Chrome, которые можно повторно использовать для создания любого расширения.

К концу этой статьи вы создадите расширение, которое выглядит и работает так, как показано в этом видео.

https://youtu.be/whdKJ7o46n0?embedable=true

Это только первая часть этого руководства. Во второй части я покажу, как расширить интерфейс расширения для выбора и загрузки захваченных изображений в виде ZIP-архива, а затем объясню, как опубликовать расширение в Google Chrome WebStore.

Базовая структура расширения

Расширение Google Chrome – это веб-приложение, которое может содержать любое количество HTML-страниц, таблиц стилей CSS, файлов JavaScript, изображений, любых других файлов и файла manifest.json в одной папке, которая определяет, как это конкретное расширение будет выглядеть и работать.

Минимальное расширение Chrome

Минимальное расширение Chrome состоит только из файла manifest.json. Это пример базового файла manifest.json, который можно использовать в качестве шаблона при создании любого нового расширения Chrome:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {},
    "action": {},
    "permissions": [],
    "background":{}
}

Единственными обязательными параметрами являются name, description, version и manifest_version. manifest_version должно быть равно 3. Значения остальных параметров на ваше усмотрение, они должны четко описывать ваше расширение и его версию. В этом примере я описал расширение Image Grabber, которое будет извлекать ссылки на все изображения с текущей страницы браузера.

Вы можете увидеть полный список параметров, которые можно указать в файле manifest.json в разделе официальная документация.

Папка с одним файлом manifest.json — это минимальное работоспособное расширение Chrome, которое можно упаковать, установить в Chrome и распространить. Это минимальное расширение будет выглядеть по умолчанию и ничего не будет делать, пока мы не определим другие параметры: иконки, action, разрешения и background. .

Итак, давайте создадим папку image_grabber и поместим файл manifest.json с этим содержимым по умолчанию. Тогда давайте просто установим это расширение в Chrome.

Установить расширение Chrome

При разработке расширения оно представляет собой папку с файлами. В терминах расширений Chrome это называется unpacked extension. После завершения разработки вам нужно будет упаковать папку расширения в архив с расширением .crx с помощью менеджера расширений Chrome. Затем этот архив можно использовать для загрузки в Интернет-магазин Chrome, откуда пользователи смогут установить ваше расширение в свои браузеры.

Чтобы протестировать и отладить расширение во время разработки, вы можете установить распакованное расширение в Chrome. Для этого введите chrome://extensions в строке URL-адреса браузера, чтобы открыть диспетчер расширений Chrome.

Чтобы устанавливать и отлаживать расширения во время разработки, включите переключатель Режим разработчика в правой части панели расширений. Появится панель управления расширениями:

Затем нажмите кнопку Загрузить распакованное и выберите папку с расширением. Укажите его на наше минимальное расширение image_grabber. Сразу после этого в списке установленных расширений появится панель расширения Image Grabber:

Панель расширения Image Grabber показывает уникальный идентификатор, описание и версию расширения. Каждый раз при изменении файла manifest.json нужно нажимать значок Reload на панели расширения, чтобы перезагрузить обновленное расширение:

Чтобы использовать расширение в браузере, вы можете найти его в списке установленных расширений Chrome. Чтобы просмотреть этот список, нажмите кнопку со значком Расширения

.

в правой части строки URL-адреса Chrome и найдите элемент «Захват изображений» в раскрывающемся списке. Вы также можете нажать кнопку со значком «Закрепить» справа от расширения, чтобы поместить значок расширения на панель инструментов браузера на одну строку с другими распространенными расширениями:

После Закрепления расширения его значок по умолчанию появится на панели инструментов:

Это все. Мы установили минимальное рабочее расширение Chrome. Однако он выглядит как простой символ «I» на сером фоне, и при нажатии на него ничего не происходит. Давайте добавим другие недостающие части в manifest.json, чтобы изменить это.

Добавить значки расширений

Параметр icons в файле manifest.json имеет формат объекта Javascript, который определяет расположение значков различных размеров. Расширение должно иметь иконки разных размеров: 16x16 px, 32x32 px, 48x48 px и 128x128 px. Иконки — это изображения в формате «.PNG», которые следует размещать в любом месте папки расширения. Файлы изображений могут иметь любые имена. Я создал 4 значка соответствующих размеров в файлах 16.png, 32.png, 48.png и 128.png и поместил их в папку icons внутри корневой папки расширения. Затем manifest.json нужно указать на эти места с помощью параметра icons, как показано ниже:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {},
    "permissions": [],
    "background":{}
}

Пути к файлам значков указываются как относительные пути.

После этого нажмите кнопку Обновить на панели расширения Image Grabber на вкладке chrome://extensions, чтобы применить измененный manifest.json. . В результате вы должны увидеть, что значок расширения на панели инструментов изменился, как показано ниже:

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

Создайте интерфейс расширения

Расширение должно что-то делать, оно должно выполнять какие-то действия, чтобы иметь смысл. Расширение позволяет запускать действия двумя способами:

* В фоновом режиме при запуске расширения * Из интерфейса расширения, когда пользователь взаимодействует с ним с помощью кнопок или других элементов управления пользовательского интерфейса. *

Расширение может использовать обе опции одновременно.

Для выполнения действий в фоновом режиме вам необходимо создать JS-скрипт и указать его расположение в параметре background файла manifest.json. Этот скрипт может определять прослушиватели для широкого спектра событий браузера, например: когда расширение установлено, когда пользователь открывает/закрывает вкладку в браузере, когда пользователь добавляет/удаляет закладку и многие другие. Затем этот скрипт будет все время работать в фоновом режиме и реагировать на каждое из этих событий, запуская код Javascript из функций обработки событий.

Для этого расширения я не буду использовать эту функцию, поэтому параметр background файла manifest.json будет пустым. Он включен только для того, чтобы сделать файл manifest.json полезным в качестве начального шаблона для любого расширения Chrome, но в расширении Image Grabber единственным действием является «Захват изображений», и он будет запускать только из пользовательского интерфейса, когда пользователь явно нажимает кнопку "ВЗЯТЬ СЕЙЧАС".

Чтобы запускать действия из интерфейса, нам нужно определить интерфейс. Интерфейсы для расширений Chrome — это HTML-страницы, которые можно комбинировать с таблицами стилей CSS для оформления этих страниц, и файлы Javascript, которые определяют действия, выполняемые при взаимодействии пользователя с элементами этого интерфейса. Основной интерфейс — это интерфейс, отображаемый, когда пользователь щелкает значок расширения на панели инструментов, и он должен быть определен в параметре action файла manifest.json. В зависимости от того, как определен интерфейс, он может открываться как новая вкладка в браузере или отображаться как всплывающее окно под кнопкой расширения, когда пользователь нажимает ее.

Расширение Image Grabber использует второй вариант. Он отображает всплывающее окно с заголовком и кнопкой «ЗАГРУЗИТЬ СЕЙЧАС». Итак, давайте определим это в manifest.json:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {
        "default_popup":"popup.html"
    },
    "permissions": [],
    "background":{}
}

Итак, как определено здесь, основной интерфейс — это всплывающее окно, и содержимое этого всплывающего окна должно быть в файле popup.html. Этот файл представляет собой обычную HTML-страницу. Итак, создайте файл popup.html в папке расширения со следующим содержимым:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
    </body>
</html>

Это простая страница с заголовком "Image Grabber" и кнопкой "GRAB NOW" с идентификатором "grabBtn".

Перейдите на страницу chrome://extensions, чтобы перезагрузить расширение Image Grabber. Теперь вы можете нажать на значок расширения, чтобы увидеть всплывающее окно с интерфейсом:

Он работает, но выглядит недостаточно идеально. Давайте стилизуем его с помощью CSS. Создайте следующий файл popup.css в папке расширения:

body {
    text-align:center;
    width:200px;
}

button {
    width:100%;
    color:white;
    background:linear-gradient(#01a9e1, #5bc4bc);
    border-width:0px;
    border-radius:20px;
    padding:5px;
    font-weight: bold;
    cursor:pointer;
}

Этот CSS определяет, что body должен иметь ширину 200 пикселей. Таким образом, размер всплывающего окна должен быть определен для расширения Chrome. Если не указано, расширение будет использовать минимальный размер, необходимый для отображения содержимого.

Затем добавьте эту таблицу стилей popup.css в заголовок страницы popup.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
        <link rel="stylesheet" type="text/css" href="popup.css"/>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
    </body>
</html>

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

Как вы могли заметить, вам не нужно перезагружать расширение каждый раз при изменении HTML или любого другого файла. Вы должны перезагружать расширение только при изменении manifest.json.

Теперь, чтобы сделать наш пользовательский интерфейс законченным, давайте добавим код Javascript для реагирования на событие нажатия кнопки «ЗАГРУЗИТЬ СЕЙЧАС». Вот одно важное замечание: Chrome не позволяет использовать встроенный Javascript на HTML-страницах расширений. Весь код Javascript должен быть определен только в отдельных файлах .js.

Вот почему создайте файл popup.js в папке расширений со следующим кодом-заполнителем:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    alert("CLICKED");
})

и включите этот файл сценария на страницу popup.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Image Grabber</title>
        <link rel="stylesheet" type="text/css" href="popup.css"/>
    </head>
    <body>
        <h1>Image Grabber</h1>
        <button id="grabBtn">GRAB NOW</button>
        <script src="popup.js"></script>
    </body>
</html>

Этот код добавляет прослушиватель событий onClick к кнопке с идентификатором grabBtn. Теперь, если вы откроете всплывающее окно расширения и нажмете кнопку «ЗАГРУЗИТЬ СЕЙЧАС», оно должно отобразить окно предупреждения с текстом «CLICKED».

Наконец, у нас есть полный макет расширения со стилизованным интерфейсом и скриптом обработки событий для него.

На данном этапе это расширение, которое можно использовать в качестве базового шаблона для начала создания широкого спектра расширений Chrome на основе всплывающего пользовательского интерфейса.

Теперь давайте реализуем «бизнес-логику» этого конкретного расширения — обработчик onClick для кнопки «ЗАГРУЗИТЬ СЕЙЧАС», чтобы получить список URL-адресов изображений с текущей страницы браузера и скопировать его в буфер обмена.

Реализовать функцию "ЗАГРУЗИТЬ СЕЙЧАС"

Используя Javascript в расширении, вы можете делать все то же, что и на веб-сайте, используя Javascript: открывать другие HTML-страницы из текущей, делать запросы к удаленным серверам, загружать данные из расширения в удаленные места и делать все остальное. Но в дополнение к этому, если этот скрипт выполняется в расширении Chrome, вы можете использовать API-интерфейсы браузера Chrome для связи с объектами браузера: для чтения из них и для их изменения. Большинство API Google Chrome доступны через пространство имен chrome. В частности, для расширения Image Grabber мы будем использовать следующие API:

* chrome.tabs — API вкладок Chrome. Он будет использоваться для доступа к активной вкладке браузера Chrome. * chrome.scripting – API сценариев Chrome. Он будет использоваться для внедрения и выполнения кода JavaScript на веб-странице, открытой на активной вкладке браузера.

Получить необходимые разрешения

По умолчанию из соображений безопасности Chrome не разрешает доступ ко всем доступным API. Расширение должно объявить, какие разрешения ему требуются, в параметре permissions файла manifest.json. Существует много разрешений, все они описаны в официальной документации здесь:

https://developer.chrome.com/docs/extensions/mv3/declare_permissions/ . Для Image Grabber нам нужны два разрешения со следующими именами:

* activeTab - для получения доступа к активной вкладке браузера * scripting — чтобы получить доступ к Chrome Scripting API для внедрения и выполнения скриптов JavaScript в разных местах браузера Chrome.

Чтобы получить эти разрешения, необходимо добавить их имена в параметр массива permissions файла manifest.json:

{
    "name": "Image Grabber",
    "description": "Extract all images from current web page",
    "version": "1.0",
    "manifest_version": 3,
    "icons": {
        "16":"icons/16.png",
        "32":"icons/32.png",
        "48":"icons/48.png",
        "128":"icons/128.png"
    },
    "action": {
        "default_popup":"popup.html",
    },
    "permissions": ["scripting", "activeTab"],
    "background":{}
}

и перезагрузите расширение на панели chrome://extensions.

Это окончательный manifest.json для этого проекта. Теперь у него есть все необходимые части: значки, ссылка на основной всплывающий интерфейс и разрешения, которые требует этот интерфейс.

Получить информацию об активной вкладке браузера

Чтобы запросить информацию о вкладках браузера, мы будем использовать функцию chrome.tabs.query со следующей подписью:

chrome.tabs.query(queryObject,callback)

* queryObject — это объект Javascript с параметрами, определяющими критерии поиска вкладок браузера, которые нам необходимо получить. * callback - это функция, которая вызывается после завершения запроса. Эта функция выполняется с одним параметром tabs, представляющим собой массив найденных вкладок, отвечающих заданным критериям поиска. Каждый элемент массива tabs является объектом Tab. Объект Tab описывает найденную вкладку и содержит уникальный идентификатор вкладки, ее заголовок и другую информацию.

Здесь я не буду полностью описывать формат queryObject и возвращаемый объект Tab. Вы можете найти эту информацию в справочнике по API chrome.tabs здесь:

https://developer.chrome.com/docs/extensions/reference/tabs/ .

Для расширения Image Grabber нам нужно запросить активную вкладку. Запрос для поиска вкладки такого типа: {active: true}.

Давайте напишем код для получения информации об активной вкладке для кнопки «ЗАГРУЗИТЬ СЕЙЧАС» в обработчике клика:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    chrome.tabs.query({active: true}, (tabs) => {
        const tab = tabs[0];
        if (tab) {
            alert(tab.id)
        } else {
            alert("There are no active tabs")
        }
    })
})

Этот код выполняет запрос, чтобы получить все активные вкладки. После завершения запроса он вызывает обратный вызов с массивом найденных вкладок в аргументе tabs. Активной может быть только одна вкладка, поэтому можно считать, что это первый и единственный элемент массива tabs. Если активная вкладка существует, мы показываем идентификатор этой вкладки в окне предупреждения (мы заменим это предупреждение разумным кодом в следующем разделе). Однако если активных вкладок нет, мы предупреждаем об этом пользователя.

Теперь, если вы откроете расширение и нажмете кнопку «ЗАГРУЗИТЬ СЕЙЧАС», оно должно отобразить окно предупреждения с числовым идентификатором активной вкладки.

В следующем разделе мы будем использовать этот идентификатор для управления содержимым веб-страницы, отображаемой на этой вкладке.

Захват изображений с текущей страницы

Расширение может взаимодействовать с открытыми страницами браузера Chrome с помощью Chrome Scripting JavaScript API, расположенного в пространстве имен chrome.scripting. В частности, мы будем использовать этот API для внедрения скрипта на веб-страницу текущей вкладки, выполнения этого скрипта и возврата результата обратно в расширение. При запуске он имеет доступ ко всему содержимому веб-страницы, на которую внедряется этот скрипт.

Единственная функция API chrome.scripting, используемая для этого расширения, — executeScript. Он имеет следующую подпись:

chrome.scripting.executeScript(injectSpec,callback)

injectSpec

Это объект типа ScriptInjection. Он определяет, где и как внедрить скрипт. Параметр target этого объекта используется для указания того, «куда» внедрить скрипт — идентификатор вкладки браузера, в которую должен быть внедрен скрипт. Затем другие параметры этого объекта определяют, «как» внедрить скрипт. Скрипт можно внедрить как:

* файл или файлы - в этом случае нужно указать массив файлов Javascript для инжекта. Файлы должны находиться в папке расширения. * функция - в этом случае нужно указать функцию для инжекта. Функция должна находиться в том же файле (popup.js).

Скрипт, который нам нужно внедрить, будет использоваться для получения всех изображений целевой страницы и возврата их URL-адресов. Это небольшой скрипт, поэтому мы внедрим его как функцию, расположенную в том же файле popup.js. Итак, injectSpec для этого случая будет выглядеть так:

{
    target:{ tabId: tab.id, allFrames: true },
    func: grabImages,
}, 

Здесь мы используем идентификатор объекта tab, который мы получили на предыдущем шаге, в качестве цели для внедрения скрипта. Кроме того, существует набор опций allFrames, который сообщает, что внедренный скрипт должен выполняться в каждом встроенном фрейме целевой страницы, если на этой странице есть встроенные фреймы. В качестве скрипта мы внедрим функцию grabImages, которая будет определена позже.

обратный вызов

Введенная функция будет выполнять действия на целевой веб-странице и на всех встроенных фреймах этой страницы (каждый фрейм также является отдельной страницей) и возвращать результат. После этого расширение выполнит функцию обратного вызова с возвращенными результатами в качестве аргумента. Аргументом функции является массив объектов типа InjectionResult для каждого кадра. Каждый объект содержит свойство «результат», которое является фактическим результатом, возвращаемым функцией grabImages.

Теперь давайте соединим все части вместе:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    chrome.tabs.query({active: true}, function(tabs) {
        var tab = tabs[0];
        if (tab) {
            chrome.scripting.executeScript(
                {
                    target:{tabId: tab.id, allFrames: true},
                    func:grabImages
                },
                onResult
            )
        } else {
            alert("There are no active tabs")
        }
    })
})

function grabImages() {
    // TODO - Query all images on a target web page
    // and return an array of their URLs
}

function onResult(frames) {
    // TODO - Combine returned arrays of image URLs,
    // join them to a single string, delimited by 
    // carriage return symbol and copy to a clipboard
}

Вот как реализована функция grabImages:

/**
 * Executed on a remote browser page to grab all images
 * and return their URLs
 * 
 *  @return Array of image URLs
 */
function grabImages() {
    const images = document.querySelectorAll("img");
    return Array.from(images).map(image=>image.src);    
}

Эта функция будет работать на целевой веб-странице, поэтому document, указанный внутри нее, является узлом документа DOM целевой веб-страницы. Эта функция запрашивает список всех узлов img из документа, затем преобразует этот список в массив и возвращает массив URL-адресов (image.src) этих изображений. Это очень сырая и простая функция, поэтому в качестве домашнего задания вы можете настроить ее: применять различные фильтры к этому списку, очищать URL-адреса, удаляя из них строки «запроса» и т. д., чтобы результирующий список выглядел идеально.

После выполнения этой функции в каждом кадре целевой веб-страницы массивы результатов будут объединены и отправлены в функцию обратного вызова onResult, которая может выглядеть следующим образом:

/**
 * Executed after all grabImages() calls finished on 
 * remote page
 * Combines results and copy a list of image URLs 
 * to clipboard
 * 
 * @param {[]InjectionResult} frames Array 
 * of grabImage() function execution results
 */
function onResult(frames) {
    // If script execution failed on the remote end 
    // and could not return results
    if (!frames || !frames.length) { 
        alert("Could not retrieve images from specified page");
        return;
    }
    // Combine arrays of the image URLs from 
    // each frame to a single array
    const imageUrls = frames.map(frame=>frame.result)
                            .reduce((r1,r2)=>r1.concat(r2));
    // Copy to clipboard a string of image URLs, delimited by 
    // carriage return symbol  
    window.navigator.clipboard
          .writeText(imageUrls.join("n"))
          .then(()=>{
             // close the extension popup after data 
             // is copied to the clipboard
             window.close();
          });
}

Не все вкладки, открытые в браузере, являются вкладками с веб-страницами внутри. Например, вкладка со списком расширений или вкладка с настройками браузера не являются вкладками с веб-страницами. Если вы попытаетесь запустить скрипт с объектом document на этих вкладках, он завершится ошибкой и ничего не вернет. Вот почему в начале функции onResult мы проверяем результат и продолжаем, только если он существует. Затем мы объединяем массивы URL-адресов изображений, возвращаемых для каждого кадра, в один массив с помощью комбинации map/reduce, а затем используем window.navigator.clipboard API для копирования присоединенных к массиву строк в буфер обмена. Функция writeText является асинхронной, поэтому нам нужно дождаться ее завершения, разрешив обещание, которое она возвращает. И когда она разрешится, мы закроем всплывающее окно расширения.

Я объяснил только одну функцию API сценариев Chrome и только в контексте расширения Image Grabber. Вы можете просмотреть полную документацию по Chrome Scripting API, чтобы уточнить все недостающие части: https://developer.chrome.com /docs/extensions/reference/scripting/ .

Очистка кода

Последнее, что я хотел бы сделать с кодом, обрабатывающим событие "GRAB NOW" onClick, – это извлечь код, выполняющий chrome.scripting, в отдельную функцию:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    // Get active browser tab
    chrome.tabs.query({active: true}, function(tabs) {
        var tab = tabs[0];
        if (tab) {
            execScript(tab);
        } else {
            alert("There are no active tabs")
        }
    })
})

/**
 * Function executes a grabImages() function on a web page,
 * opened on specified tab
 * @param tab - A tab to execute script on
 */
function execScript(tab) {
    // Execute a function on a page of the current browser tab
    // and process the result of execution
    chrome.scripting.executeScript(
        {
            target:{tabId: tab.id, allFrames: true},
            func:grabImages
        },
        onResult
    )
}

И окончательное содержимое popup.js выглядит следующим образом:

const grabBtn = document.getElementById("grabBtn");
grabBtn.addEventListener("click",() => {    
    // Get active browser tab
    chrome.tabs.query({active: true}, function(tabs) {
        var tab = tabs[0];
        if (tab) {
            execScript(tab);
        } else {
            alert("There are no active tabs")
        }
    })
})

/**
 * Execute a grabImages() function on a web page,
 * opened on specified tab and on all frames of this page
 * @param tab - A tab to execute script on
 */
function execScript(tab) {
    // Execute a function on a page of the current browser tab
    // and process the result of execution
    chrome.scripting.executeScript(
        {
            target:{tabId: tab.id, allFrames: true},
            func:grabImages
        },
        onResult
    )
}

/**
 * Executed on a remote browser page to grab all images
 * and return their URLs
 * 
 *  @return Array of image URLs
 */
function grabImages() {
    const images = document.querySelectorAll("img");
    return Array.from(images).map(image=>image.src);    
}

/**
 * Executed after all grabImages() calls finished on 
 * remote page
 * Combines results and copy a list of image URLs 
 * to clipboard
 * 
 * @param {[]InjectionResult} frames Array 
 * of grabImage() function execution results
 */
function onResult(frames) {
    // If script execution failed on remote end 
    // and could not return results
    if (!frames || !frames.length) { 
        alert("Could not retrieve images from specified page");
        return;
    }
    // Combine arrays of image URLs from 
    // each frame to a single array
    const imageUrls = frames.map(frame=>frame.result)
                            .reduce((r1,r2)=>r1.concat(r2));
    // Copy to clipboard a string of image URLs, delimited by 
    // carriage return symbol  
    window.navigator.clipboard
          .writeText(imageUrls.join("n"))
          .then(()=>{
             // close the extension popup after data 
             // is copied to the clipboard
             window.close();
          });
}

Заключение

После этого вы можете открыть любую веб-страницу браузера с изображениями, щелкнуть расширение Image Grabber, чтобы открыть его всплывающий интерфейс, а затем нажать кнопку «ЗАГРУЗИТЬ СЕЙЧАС». Затем вставьте содержимое буфера обмена в любой текстовый редактор. Он должен вставить список абсолютных URL-адресов всех изображений с этой веб-страницы.

Вы можете клонировать и использовать полный исходный код этого расширения из моего репозитория GitHub: https://github.com/AndreyGermanov/image_grabber. . Однако я бы порекомендовал создать это расширение с нуля, читая эту статью.

Это только первая часть туториала, связанная с этим расширением. Во второй части я буду использовать этот список URL-адресов изображений для создания дополнительного интерфейса для этого расширения, который позволит загружать все или выбранные изображения из этого списка в виде одного ZIP-архива. Это определенно полезнее, чем просто иметь список URL-адресов в буфере обмена. Кроме того, я покажу, как упаковать готовое расширение и загрузить его в Интернет-магазин Chrome, что сделает его доступным для всех.

Не стесняйтесь подключаться и следить за мной в социальных сетях, где я публикую объявления о своих статьях, подобных этой и другим новостям разработки программного обеспечения:

LinkedIn: https://www.linkedin.com/in/andrey-germanov-dev/ Facebook: https://web.facebook.com/AndreyGermanovDev Твиттер: https://twitter.com/GermanovDev

Мой сайт онлайн-сервисов: https://germanov.dev

Удачного программирования, ребята!


Также опубликовано здесь


Оригинал