日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

golang使用chrome headless获取网页内容

發(fā)布時間:2023/12/13 综合教程 31 生活家
生活随笔 收集整理的這篇文章主要介紹了 golang使用chrome headless获取网页内容 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

如今動態(tài)渲染的頁面越來越多,爬蟲們或多或少都需要用到headless browser來渲染待爬取的頁面。

而最近廣泛使用的headless browser解決方案PhantomJS已經(jīng)宣布不再繼續(xù)維護,轉(zhuǎn)而推薦使用headless chrome。

那么headless chrome究竟是什么呢,Headless Chrome 是 Chrome 瀏覽器的無界面形態(tài),可以在不打開瀏覽器的前提下,使用所有 Chrome 支持的特性運行你的程序。

簡而言之,除了沒有圖形界面,headless chrome具有所有現(xiàn)代瀏覽器的特性,可以像在其他現(xiàn)代瀏覽器里一樣渲染目標(biāo)網(wǎng)頁,并能進行網(wǎng)頁截圖,獲取cookie,獲取html等操作。

詳細(xì)信息可以在這獲?。篽ttps://developers.google.cn/web/updates/2017/04/headless-chrome

有關(guān)headless chrome如何使用網(wǎng)上有許多不錯的文章,這里就不重復(fù)了。

想要在golang程序里使用headless chrome,需要借助一些開源庫,實現(xiàn)和headless chrome交互的庫有很多,這里選擇chromedp,接口和Selenium類似,易上手。

安裝:

go get -u github.com/chromedp/chromedp

引入:

import (
	"github.com/chromedp/chromedp"
        // runner用于配置headless chrome
	"github.com/chromedp/chromedp/runner" // 新版本中不需要再導(dǎo)入這個包了
)

  

創(chuàng)建headless chrome實例,每一個實例就相當(dāng)于一個瀏覽器,可以用它瀏覽、調(diào)試網(wǎng)頁內(nèi)容,默認(rèn)情況下chromedp會直接啟動帶GUI的chrome,所以需要使用runner啟動headless chrome。默認(rèn)端口為9222,可以自定義。

需要注意,chromedp在0.1.4版本中對api進行了較大的改動,因此接下來的示例中我會給出新api的用法,同時保留0.1.3及以前版本適用的例子。

// NewHeadless 創(chuàng)建headless chrome實例
// chromedp內(nèi)部有自己的超時設(shè)置,你也可以通過ctx來設(shè)置更短的超時
func NewHeadless(ctx context.Context, starturl string) (*chromedp.CDP, error) {
	// runner.Flag設(shè)置啟動headless chrome時的命令行參數(shù)
        // runner.URL設(shè)置啟動時打開的URL
        // Windows用戶需要設(shè)置runner.Flag("disable-gpu", true),具體信息參見文檔的FAQ
        run, err := runner.New(runner.Flag("headless", true),
		runner.URL(starturl))

	if err != nil {
		return nil, err
	}

        // run.Start啟動實例
	err = run.Start(ctx)
	if err != nil {
		return nil, err
	}

        // 默認(rèn)情況chromedp會輸出大量log,因為是示例所以選擇屏蔽,dropChromeLogs為自定義函數(shù),形式為func(string, ...interface{}){}
        // 使用runner初始化chromedp實例
        // 實例在使用完畢后需要調(diào)用c.Shutdown()來釋放資源
	c, err := chromedp.New(ctx, chromedp.WithRunner(run), chromedp.WithErrorf(dropChromeLogs))
	if err != nil {
		return nil, err
	}

	return c, nil
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cdp := NewHeadless(ctx, "www.cnblogs.com")

下面是0.1.4版本的api:

// 新版本中取消了cdp,將broeser對象和context合并在一起,方便了我們的操作
func NewHeadless() (context.Context, context.CancelFunc) {
    opts := make([]chromedp.ExecAllocatorOption, 0)
    opts = append(opts, chromedp.ProxyServer("http://127.0.0.1:8118"))
    opts = append(opts, chromedp.Flag("headless", true))
    allocator, cancel := chromedp.NewAllocator(context.Background(), chromedp.WithExecAllocator(opts...))
    return allocator, cancel
}

ctxt, cancel1 := NewHeadless()
defer cance1l()
c, cancel2 := chromedp.NewContext(ctxt)
defer cancel2()

新版本中不會輸出多余的log,同時也會默認(rèn)啟用headless模式。

如果你需要在新版本的chromedp啟動實例時指定一個url,你可以這樣做:

broswer := chromedp.NewBroswer(c, startURL)
chromedp.FromContext(c).Browser = browser

實例啟動后我們就能通過這個實例來訪問你想爬取的URL了。

chromedp的實例類型為*chromedp.CDP,它擁有一個func (c *CDP) Run(ctxt context.Context, a Action) error方法來執(zhí)行所有的操作。

在新版本中chromedp通過Run方法執(zhí)行所有操作,chromedp.CDP對象被chrome.Context取代,其原型為func Run(ctx context.Context, actions ...Action) error

Action是chromedp的api返回的對象,代表對headless chrome的一個操作,多個操作可以放入chromedp.Tasks里,它是一個元素為Action的slice,也可以作為Run的參數(shù)調(diào)用。

下面是部分常用的api:

// chromedp.Sleep使headless chrome睡眠d表示的時間長度
func Sleep(d time.Duration) Action

// chromedp.Navigate使瀏覽器訪問參數(shù)給出的URL
func Navigate(urlstr string) Action

// chromedp.SendKeys向指定的html元素內(nèi)輸入內(nèi)容
// sel是選擇器字符串或是選擇器要求的數(shù)據(jù)類型
// opts指定使用何種選擇器
// 常用的選擇器有:
// chromedp.ByID:根據(jù)id來選擇元素
// chromedp.ByQuery:根據(jù)DOM.querySelector的規(guī)則選擇元素
func SendKeys(sel interface{}, v string, opts ...QueryOption) Action

// chromedp.Submit將指定的元素(通常是form)提交
func Submit(sel interface{}, opts ...QueryOption) Action

// chromedp.WaitReady等待指定元素加載完畢
func WaitReady(sel interface{}, opts ...QueryOption) Action

// chromedp.Click在指定元素上觸發(fā)鼠標(biāo)點擊事件
func Click(sel interface{}, opts ...QueryOption) Action

// chromedp.OuterHTML獲取指定元素的HTML代碼(包括其子元素)
// html參數(shù)用于存放返回的HTML
func OuterHTML(sel interface{}, html *string, opts ...QueryOption) Action

  

一個獲取頁面內(nèi)容的小例子,更多例子在 https://github.com/chromedp/examples

// 獲取服務(wù)列表
func GetServiceList(res *string) chromedp.Tasks {
	return chromedp.Tasks{
		// 訪問服務(wù)列表
		chromedp.Navigate(ServiceListURL),
		// 等待直到body加載完畢
		chromedp.WaitReady("servicesList", chromedp.ByID),
		// 選擇顯示可用服務(wù)
		chromedp.Click("statusActive", chromedp.ByID),
                // 等待列表渲染
		chromedp.Sleep(2 * time.Second),
		// 獲取獲取服務(wù)列表HTML
		chromedp.OuterHTML("#servicesList table", res, chromedp.ByQuery),
	}
}

var html string
// cdp是chromedp實例
// ctx是創(chuàng)建cdp時使用的context.Context
err := cdp.Run(ctx, GetServiceList(&html) )
if err != nil {
    // 錯誤處理
}

// 成功取得HTML內(nèi)容進行后續(xù)處理
fmt.Println(html)

新版本的示例:

var html string
// ctxt是chromedp的實例,用于執(zhí)行網(wǎng)頁操作
err := chromedp,Run(ctxt, GetServiceList(&html))
if err != nil {
    // error handle
}

// 成功取得數(shù)據(jù)
fmt.Println(html)

另外新版本中關(guān)閉chrome實例的方式也有所不同:

// 釋放所有資源,并等待釋放結(jié)束
cancel2()
// 官方給的是chromedp,FromContext(ctxt).Wait(),但是目前沒有實現(xiàn)Wait方法
// 因此你可以像這樣
chromedp.FromContext(ctxt).Broswer.Shutdown()
chromedp.FromContext(ctxt).Allocator,Wait()

因為目前新版本還很不穩(wěn)定,所以推薦使用0.1.3版本。

至此golang通過chromedp(https://github.com/chromedp/chromedp)使用headless chrome進行動態(tài)網(wǎng)頁的渲染和操作就介紹完了。

希望這篇文章能給你帶來幫助,如有錯誤之處,歡迎交流指正。

總結(jié)

以上是生活随笔為你收集整理的golang使用chrome headless获取网页内容的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。