Делаем скриншот веб-страницы с помощью Go
September 07, 2020
Go — приличный инструмент автоматизации нудных действий. К примеру, можно управлять своим браузером. Давайте, для примера, сделаем скриншот какой-нибудь страницы сайта. Для этого нам потребуется установленный хром (а он есть у подавляющего количества людей, тем более разработчиков) и два десятка строк на go. Для этого нам понадобится github.com/chromedp/chromedp — библиотека го, реализующая дебаг протокол хрома.
Код состоит из нескольких частей:
- запуск хрома в headless режиме (в фоновом, его окошко не покажется)
- разбор переданных параметров в программу
- запуск команд, которые мы хотим, чтобы сделал хром. В нашем случае он должен открыть страницу и сделать её скриншот.
- сохранение скриншота в файл
Что же, к коду:
package main
import (
"context"
"io/ioutil"
"log"
"os"
"github.com/chromedp/cdproto/page"
"github.com/chromedp/chromedp"
"github.com/gosimple/slug"
)
func main() {
// Стартуем хром
ctx, cancel := chromedp.NewContext(context.Background())
// Не забываем, что его надо закрыть
// при выходе из main вызовется cancel и он передаст
// хрому о закрытии
defer cancel()
// первым аргументом скрипт принимает адрес страницы
url := os.Args[1]
// второй, опциональный аргумент, куда записывать скриншот
// если не передан, то сохраним в png файл, соответствующий url
// вырезав все лишнее из него библиотечкой slug
var filename string
if len(os.Args) == 3 {
filename = os.Args[2]
} else {
filename = slug.Make(url) + ".png"
}
// инициализируем пустой массив, куда будет сохранен скриншот
var imageBuf []byte
// и отправляем хрому задачи, которые он должен выполнить
// у нас только одна - ScreenshotTasks, но можно закинуть сколько угодно
if err := chromedp.Run(
ctx,
ScreenshotTasks(url, &imageBuf),
); err != nil {
log.Fatal(err)
}
// Задача выполнена, можно сохранить полученное изображение в файл
if err := ioutil.WriteFile(filename, imageBuf, 0644); err != nil {
log.Fatal(err)
}
}
// ScreenshotTasks записывает в imageBuf скриншот страницы, расположенной на url
func ScreenshotTasks(url string, imageBuf *[]byte) chromedp.Tasks {
return chromedp.Tasks{
// задача (таска) состоит из последовательности действий
// сначала мы переходим по заданному url
chromedp.Navigate(url),
// а теперь делаем скриншот, записывая его в imageBuf
chromedp.ActionFunc(func(ctx context.Context) (err error) {
*imageBuf, err = page.CaptureScreenshot().Do(ctx)
return err
}),
}
}
Чуть ли не каждая строка прокомментирована, так что разобраться не будет проблемой.
Для запуска:
go run main.go https://wcademy.ru/
И в папке у нас появится файл https-wcademy-ru.png
:
С тем же подходом можно заставить хром делать значительно более сложные штуки, автоматизируя любую рутину. Если интеерсно, то вот доки.
Попробовать, в две команды, можно прямо установив её из репозитория (по прежнему нужен го и хром):
go get -u github.com/wcademy/golang-tutorials/webscreenshot # ставим
И теперь в ${GOPATH}/bin
появился бинарник webscreenshot
, которым можно пользоваться:
webscreenshot https://wcademy.ru/ 1.png
Всем спасибо. До связи. Полный код, как всегда, в нашей репе.