Created
April 16, 2018 19:36
-
-
Save djmally/80cda4b9d8f1e3728d50f6a89f4e3382 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"time" | |
"github.com/mafredri/cdp" | |
"github.com/mafredri/cdp/devtool" | |
"github.com/mafredri/cdp/protocol/input" | |
"github.com/mafredri/cdp/protocol/network" | |
"github.com/mafredri/cdp/protocol/page" | |
"github.com/mafredri/cdp/protocol/runtime" | |
"github.com/mafredri/cdp/rpcc" | |
) | |
func main() { | |
// Demo program that clicks, focuses, and injects text into an <input> | |
// element on some webpage. | |
// | |
// Assumes a Chrome browser instance listening on `localhost:9222`. | |
// | |
// Change the `example.com` URL below to your desired | |
// page. Note that you won't see any useful results if the page doesn't | |
// have any <input> tags on it. | |
client := createClient() | |
// *** CHANGE THIS TO YOUR DESIRED URL *** ----------------------------------------------v | |
_, err := client.Page.Navigate(context.Background(), page.NewNavigateArgs("http://www.example.com")) | |
if err != nil { | |
panic(err.Error()) | |
} | |
// Try to click on some input element | |
if _, err := client.Runtime.Evaluate(context.Background(), runtime.NewEvaluateArgs("document.querySelector(\"input\").click()")); err != nil { | |
panic(err.Error()) | |
} | |
// Try to focus on some input element | |
if _, err := client.Runtime.Evaluate(context.Background(), runtime.NewEvaluateArgs("document.querySelector(\"input\").focus()")); err != nil { | |
panic(err.Error()) | |
} | |
// Enter text | |
password := "hunter2" | |
for _, char := range password { | |
err := client.Input.DispatchKeyEvent(context.Background(), input.NewDispatchKeyEventArgs("keyDown").SetText(string(char))) | |
if err != nil { | |
panic(err.Error()) | |
} | |
} | |
} | |
// creatClient repeatedly attempts to connect to Chrome, and returns a client instance once it connects | |
func createClient() *cdp.Client { | |
var client *cdp.Client | |
for client == nil { | |
var err error | |
client, err = connectDevtools("localhost", 9222) | |
if err != nil { | |
fmt.Println("Error connecting to Chrome", "error", err) | |
fmt.Println("Retrying connection....") | |
} | |
time.Sleep(1 * time.Second) | |
} | |
return client | |
} | |
// newClient creates a CDP client and performs some domain initialization | |
func newClient(conn *rpcc.Conn) (*cdp.Client, error) { | |
client := cdp.NewClient(conn) | |
// Enable various domains on the client | |
if err := client.Runtime.Enable(context.Background()); err != nil { | |
return nil, err | |
} | |
if err := client.Network.Enable(context.Background(), network.NewEnableArgs()); err != nil { | |
return nil, err | |
} | |
if err := client.Page.Enable(context.Background()); err != nil { | |
return nil, err | |
} | |
return client, nil | |
} | |
// connectDevtools performs the actual browser connection and RPCC setup | |
func connectDevtools(host string, port uint16) (*cdp.Client, error) { | |
// Create a devtools instance | |
dt := devtool.New(fmt.Sprintf("http://%s:%d", host, port)) | |
// Select the page (tab) context in the browser | |
target, err := dt.Get(context.Background(), devtool.Page) | |
if err != nil { | |
// If there was no page context, create a new one | |
target, err = dt.Create(context.Background()) | |
if err != nil { | |
return nil, err | |
} | |
} | |
// Initiate a new RPC connection to the Chrome Debugging Protocol target. | |
conn, err := rpcc.DialContext( | |
context.Background(), | |
target.WebSocketDebuggerURL, | |
rpcc.WithWriteBufferSize(104857586), | |
) | |
if err != nil { | |
return nil, err | |
} | |
return newClient(conn) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment