{wcademy}

Делаем скриншот веб-страницы с помощью 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: скриншот скриншота сайта wcademy.ru

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

Попробовать, в две команды, можно прямо установив её из репозитория (по прежнему нужен го и хром):

go get -u github.com/wcademy/golang-tutorials/webscreenshot # ставим

И теперь в ${GOPATH}/bin появился бинарник webscreenshot, которым можно пользоваться:

webscreenshot https://wcademy.ru/ 1.png

Всем спасибо. До связи. Полный код, как всегда, в нашей репе.

🚀  Если узнал из статьи что-то полезное, ставь лайк и подписывайся на наш канал в Телеграм или группу ВК. Обсудить статью можно в нашем уютном чатике 😏

© 2019 - 2022, {wcademy}