Skip to content

Instantly share code, notes, and snippets.

@jerryan999
Last active August 6, 2022 15:23
Show Gist options
  • Save jerryan999/47bf118092655084ebfb9d17cdfcd606 to your computer and use it in GitHub Desktop.
Save jerryan999/47bf118092655084ebfb9d17cdfcd606 to your computer and use it in GitHub Desktop.
How to use chromedp to do a bunch of screenshot tasks on Mac
var (
CHROME_EXEC_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
USER_DATA_DIR = fmt.Sprintf("/Users/%s/Library/Application Support/Google/Chrome/", GetCurrentUserName())
PROFILE_DIRECTORY = "Default"
)
func GetCurrentUserName() string {
currentUser, _ := user.Current()
username := currentUser.Username
return username
}
func main() {
opts := append(
chromedp.DefaultExecAllocatorOptions[:0], // No default options to provent chrome account login problems.
chromedp.ExecPath(CHROME_EXEC_PATH),
chromedp.DisableGPU,
chromedp.UserDataDir(USER_DATA_DIR),
chromedp.Flag("profile-directory", PROFILE_DIRECTORY),
chromedp.Flag("headless", false),
chromedp.Flag("flag-switches-begin", true),
chromedp.Flag("flag-switches-end", true),
chromedp.Flag("enable-automation", false),
chromedp.Flag("disable-blink-features", "AutomationControlled"),
chromedp.Flag("new-window", true),
)
c, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()
// create a new browser
chromeCtx, cancel := chromedp.NewContext(
c,
)
defer cancel()
// Execute an empty task to user
chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
}
// It is a Google Analytics Marketing Website which tracks a series of metrics as shown below.
// Getting
package main
import (
"context"
"fmt"
"io/ioutil"
"log"
"os/user"
"time"
"github.com/chromedp/chromedp"
)
var (
CHROME_EXEC_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
USER_DATA_DIR = fmt.Sprintf("/Users/%s/Library/Application Support/Google/Chrome/", GetCurrentUserName())
PROFILE_DIRECTORY = "Default"
)
func GetCurrentUserName() string {
currentUser, _ := user.Current()
username := currentUser.Username
return username
}
func main() {
opts := append(
chromedp.DefaultExecAllocatorOptions[:0], // No default options to provent chrome account login problems.
chromedp.ExecPath(CHROME_EXEC_PATH),
chromedp.DisableGPU,
chromedp.UserDataDir(USER_DATA_DIR),
chromedp.Flag("profile-directory", PROFILE_DIRECTORY),
chromedp.Flag("headless", false),
chromedp.Flag("flag-switches-begin", true),
chromedp.Flag("flag-switches-end", true),
chromedp.Flag("enable-automation", false),
chromedp.Flag("disable-blink-features", "AutomationControlled"),
chromedp.Flag("new-window", true),
)
c, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()
// create a new browser
chromeCtx, cancel := chromedp.NewContext(
c,
)
defer cancel()
// Execute an empty task to user
chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
// the screenshot calling part is easy to understand.
var targets []Target = []Target{
{"https://datastudio.google.com/u/0/reporting/0B_U5RNpwhcE6SF85TENURnc4UjA/preview", "datastudio", 966, 1308},
}
for _, target := range targets {
var buf []byte
// start the browser
if err := chromedp.Run(chromeCtx,
Screenshot(target, 100, &buf)); err != nil {
log.Fatal(err)
}
// capture
file := fmt.Sprintf("report-%s.png", target.Name)
if err := ioutil.WriteFile(file, buf, 0o644); err != nil {
log.Fatal(err)
}
}
log.Printf("Successfully wrote Screenshot.png")
}
// Second, The main screenshot function definition is below.
// - Navigate to the target web page.
// - Emulate the viewport size according to the target parameters.
// - Sleep for 10 seconds.
// - Capture the screenshot.
//
func Screenshot(target Target, quality int, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.Navigate(target.Url),
chromedp.EmulateViewport(int64(target.ViewX), int64(target.ViewY)),
chromedp.Sleep(10 * time.Second),
chromedp.FullScreenshot(res, quality),
}
}
// target web page and it's viewport size
type Target struct {
Url string `json:"url"`
Name string `json:"name"`
ViewX int `json:"viewX"`
ViewY int `json:"viewY"`
}
var targets []Target = []Target{
{"https://datastudio.google.com/u/0/reporting/0B_U5RNpwhcE6SF85TENURnc4UjA/preview", "datastudio", 966, 1308},
}
for _, target := range targets {
var buf []byte
// start the browser
if err := chromedp.Run(chromeCtx,
Screenshot(target, 100, &buf)); err != nil {
log.Fatal(err)
}
// capture
file := fmt.Sprintf("report-%s.png", target.Name)
if err := ioutil.WriteFile(file, buf, 0o644); err != nil {
log.Fatal(err)
}
}
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/user"
"time"
"github.com/chromedp/chromedp"
)
var (
CHROME_EXEC_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
USER_DATA_DIR = fmt.Sprintf("/Users/%s/Library/Application Support/Google/Chrome/", GetCurrentUserName())
)
func GetCurrentUserName() string {
currentUser, _ := user.Current()
username := currentUser.Username
return username
}
type Target struct {
Url string `json:"url"`
Name string `json:"name"`
ViewX int `json:"viewX"`
ViewY int `json:"viewY"`
}
var (
urlsFile = flag.String("inputfile", "urls.json", "a file containing urls to screenshot")
profile = flag.String("profile", "Default", "choose which profile to use, enter chrome://version/ to see your profile")
sleep = flag.Int("sleep", 5, "sleep seconds between each screenshot")
)
func main() {
flag.Parse()
// check file existing
content, err := ioutil.ReadFile(*urlsFile)
if err != nil {
log.Fatal(err)
}
fmt.Println("Current user is :", GetCurrentUserName())
fmt.Println("Current profile directory is:", *profile)
opts := append(
chromedp.DefaultExecAllocatorOptions[:0], // No default options to provent chrome account login problems.
chromedp.ExecPath(CHROME_EXEC_PATH),
chromedp.DisableGPU,
chromedp.UserDataDir(USER_DATA_DIR),
chromedp.Flag("profile-directory", *profile),
chromedp.Flag("headless", false),
chromedp.Flag("flag-switches-begin", true),
chromedp.Flag("flag-switches-end", true),
chromedp.Flag("enable-automation", false),
chromedp.Flag("disable-blink-features", "AutomationControlled"),
chromedp.Flag("new-window", true),
)
c, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()
// create context
chromeCtx, cancel := chromedp.NewContext(
c,
)
defer cancel()
// Execute an empty task to user
chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
// parse content into json array
fmt.Println("Starting to screenshot")
var targets []Target
err = json.Unmarshal(content, &targets)
if err != nil {
log.Fatal(err)
}
currentDate := time.Now().Format("2006-01-02")
fmt.Println("YYYY-MM-DD : ", currentDate)
// make folder if not exist
os.Mkdir(currentDate, 0755)
for _, target := range targets {
func(name string, url string) {
var buf []byte
// capture entire browser viewport, returning png with quality=90
if err := chromedp.Run(chromeCtx,
fullScreenshot(target, 100, &buf)); err != nil {
log.Fatal(err)
}
// capture
file := fmt.Sprintf("%s/report-%s.png", currentDate, name)
if err := ioutil.WriteFile(file, buf, 0o644); err != nil {
log.Fatal(err)
}
log.Printf("%s saved", file)
}(target.Name, target.Url)
}
log.Printf("Successfully wrote fullScreenshot.png")
}
func fullScreenshot(target Target, quality int, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.Navigate(target.Url),
chromedp.Click(`span.mat-mdc-button-touch-target`, chromedp.NodeVisible),
chromedp.EmulateViewport(int64(target.ViewX), int64(target.ViewY)),
chromedp.WaitVisible(`.tableBody`),
chromedp.WaitVisible(`.valueLabel`),
chromedp.WaitReady(`.tableBody`),
chromedp.WaitReady(`.valueLabel`),
chromedp.Sleep(time.Duration(*sleep) * time.Second),
// chromedp.EvaluateAsDevTools(js, nil),
chromedp.FullScreenshot(res, quality),
}
}
type Target struct {
Url string `json:"url"`
Name string `json:"name"`
ViewX int `json:"viewX"`
ViewY int `json:"viewY"`
}
func Screenshot(target Target, quality int, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.Navigate(target.Url),
chromedp.EmulateViewport(int64(target.ViewX), int64(target.ViewY)),
chromedp.Sleep(10 * time.Second),
chromedp.FullScreenshot(res, quality),
}
}
[
{
"url": "https://datastudio.google.com/u/1/reporting/c11a5b80-55d1-40aa-9666-9fe0e81cc902/page/u86rB?params=%7B%22df173%22:%22include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580IOS%22%7D",
"name": "dof2-ios",
"viewX":1300,
"viewY":1470
},
{
"url": "https://datastudio.google.com/u/1/reporting/c11a5b80-55d1-40aa-9666-9fe0e81cc902/page/u86rB?params=%7B%22df173%22:%22include%25EE%2580%25800%25EE%2580%2580IN%25EE%2580%2580ANDROID%22%7D",
"name": "dof2-android",
"viewX":1300,
"viewY":1470
},
{
"url": "https://datastudio.google.com/u/1/reporting/9bd45efe-57ac-4a81-8f1a-c2aafd76c6b2/page/NRKVB",
"name":"Downloader",
"viewX":1300,
"viewY":1477
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment