/example_test.go

https://github.com/mafredri/cdp · Go · 139 lines · 103 code · 24 blank · 12 comment · 35 complexity · b22b34315ecaa8c8d6fb31b3d0fcba0f MD5 · raw file

  1. package cdp_test
  2. import (
  3. "bufio"
  4. "context"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "os"
  9. "time"
  10. "github.com/mafredri/cdp"
  11. "github.com/mafredri/cdp/devtool"
  12. "github.com/mafredri/cdp/protocol/dom"
  13. "github.com/mafredri/cdp/protocol/page"
  14. "github.com/mafredri/cdp/rpcc"
  15. )
  16. func Example() {
  17. err := run(5 * time.Second)
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. }
  22. func run(timeout time.Duration) error {
  23. ctx, cancel := context.WithTimeout(context.Background(), timeout)
  24. defer cancel()
  25. // Use the DevTools HTTP/JSON API to manage targets (e.g. pages, webworkers).
  26. devt := devtool.New("http://127.0.0.1:9222")
  27. pt, err := devt.Get(ctx, devtool.Page)
  28. if err != nil {
  29. pt, err = devt.Create(ctx)
  30. if err != nil {
  31. return err
  32. }
  33. }
  34. // Initiate a new RPC connection to the Chrome DevTools Protocol target.
  35. conn, err := rpcc.DialContext(ctx, pt.WebSocketDebuggerURL)
  36. if err != nil {
  37. return err
  38. }
  39. defer conn.Close() // Leaving connections open will leak memory.
  40. c := cdp.NewClient(conn)
  41. // Open a DOMContentEventFired client to buffer this event.
  42. domContent, err := c.Page.DOMContentEventFired(ctx)
  43. if err != nil {
  44. return err
  45. }
  46. defer domContent.Close()
  47. // Enable events on the Page domain, it's often preferrable to create
  48. // event clients before enabling events so that we don't miss any.
  49. if err = c.Page.Enable(ctx); err != nil {
  50. return err
  51. }
  52. // Create the Navigate arguments with the optional Referrer field set.
  53. navArgs := page.NewNavigateArgs("https://www.google.com").
  54. SetReferrer("https://duckduckgo.com")
  55. nav, err := c.Page.Navigate(ctx, navArgs)
  56. if err != nil {
  57. return err
  58. }
  59. // Wait until we have a DOMContentEventFired event.
  60. if _, err = domContent.Recv(); err != nil {
  61. return err
  62. }
  63. fmt.Printf("Page loaded with frame ID: %s\n", nav.FrameID)
  64. // Fetch the document root node. We can pass nil here
  65. // since this method only takes optional arguments.
  66. doc, err := c.DOM.GetDocument(ctx, nil)
  67. if err != nil {
  68. return err
  69. }
  70. // Get the outer HTML for the page.
  71. result, err := c.DOM.GetOuterHTML(ctx, &dom.GetOuterHTMLArgs{
  72. NodeID: &doc.Root.NodeID,
  73. })
  74. if err != nil {
  75. return err
  76. }
  77. fmt.Printf("HTML: %s\n", result.OuterHTML)
  78. // Capture a screenshot of the current page.
  79. screenshotName := "screenshot.jpg"
  80. screenshotArgs := page.NewCaptureScreenshotArgs().
  81. SetFormat("jpeg").
  82. SetQuality(80)
  83. screenshot, err := c.Page.CaptureScreenshot(ctx, screenshotArgs)
  84. if err != nil {
  85. return err
  86. }
  87. if err = ioutil.WriteFile(screenshotName, screenshot.Data, 0644); err != nil {
  88. return err
  89. }
  90. fmt.Printf("Saved screenshot: %s\n", screenshotName)
  91. pdfName := "page.pdf"
  92. f, err := os.Create(pdfName)
  93. if err != nil {
  94. return err
  95. }
  96. pdfArgs := page.NewPrintToPDFArgs().
  97. SetTransferMode("ReturnAsStream") // Request stream.
  98. pdfData, err := c.Page.PrintToPDF(ctx, pdfArgs)
  99. if err != nil {
  100. return err
  101. }
  102. sr := c.NewIOStreamReader(ctx, *pdfData.Stream)
  103. r := bufio.NewReader(sr)
  104. // Write to file in ~r.Size() chunks.
  105. _, err = r.WriteTo(f)
  106. if err != nil {
  107. return err
  108. }
  109. err = f.Close()
  110. if err != nil {
  111. return err
  112. }
  113. fmt.Printf("Saved PDF: %s\n", pdfName)
  114. return nil
  115. }