欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

golang使用chrome headless获取网页内容

程序员文章站 2022-03-03 22:13:31
如今动态渲染的页面越来越多,爬虫们或多或少都需要用到headless browser来渲染待爬取的页面。 而最近广泛使用的headless browser解决方案PhantomJS已经宣布不再继续维护,转而推荐使用headless chrome。 那么headless chrome究竟是什么呢,He ......

如今动态渲染的页面越来越多,爬虫们或多或少都需要用到headless browser来渲染待爬取的页面。

而最近广泛使用的headless browser解决方案PhantomJS已经宣布不再继续维护,转而推荐使用headless chrome。

那么headless chrome究竟是什么呢,Headless Chrome 是 Chrome 浏览器的*面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。

简而言之,除了没有图形界面,headless chrome具有所有现代浏览器的特性,可以像在其他现代浏览器里一样渲染目标网页,并能进行网页截图,获取cookie,获取html等操作。

详细信息可以在这获取:https://developers.google.cn/web/updates/2017/04/headless-chrome

有关headless chrome如何使用网上有许多不错的文章,这里就不重复了。

想要在golang程序里使用headless chrome,需要借助一些开源库,实现和headless chrome交互的库有很多,这里选择chromedp,接口和Selenium类似,易上手。

安装:

go get -u github.com/chromedp/chromedp

引入:

import (
	"github.com/chromedp/chromedp"
        // runner用于配置headless chrome
	"github.com/chromedp/chromedp/runner"
)

  

创建headless chrome实例,每一个实例就相当于一个浏览器,可以用它浏览、调试网页内容,默认情况下chromedp会直接启动带GUI的chrome,所以需要使用runner启动headless chrome。默认端口为9222,可以自定义。

// NewHeadless 创建headless chrome实例
// chromedp内部有自己的超时设置,你也可以通过ctx来设置更短的超时
func NewHeadless(ctx context.Context, starturl string) (*chromedp.CDP, error) {
	// runner.Flag设置启动headless chrome时的命令行参数
        // runner.StartURL设置启动时打开的URL
        // Windows用户需要设置runner.Flag("disable-gpu", true),具体信息参见文档的FAQ
        run, err := runner.New(runner.Flag("headless", true),
		runner.StartURL(starturl))

	if err != nil {
		return nil, err
	}

        // run.Start启动实例
	err = run.Start(ctx)
	if err != nil {
		return nil, err
	}

        // 默认情况chromedp会输出大量log,因为是示例所以选择屏蔽
	drop := chromedp.LogFunc(dropChromeLogs)
        // 使用runner初始化chromedp实例
        // 实例在使用完毕后需要调用c.Shutdown()来释放资源
	c, err := chromedp.New(ctx, chromedp.WithRunner(run), chromedp.WithErrorf(drop))
	if err != nil {
		return nil, err
	}

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

  

实例启动后我们就能通过这个实例来访问你喜欢的URL了。

chromedp的实例类型为*chromedp.CDP,它拥有一个func (c *CDP) Run(ctxt context.Context, a Action) error 方法来执行所有的操作。

Action是chromedp的api返回的对象,代表对headless chrome的一个操作,多个操作可以放入chromedp.Tasks里,它是一个元素为Action的slice,也可以作为Run的参数调用。

下面是部分常用的api:

// chromedp.Sleep使headless chrome睡眠d表示的时间长度
func Sleep(d time.Duration) Action

// chromedp.Navigate使浏览器访问参数给出的URL
func Navigate(urlstr string) Action

// chromedp.SendKeys向指定的html元素内输入内容
// sel是选择器字符串或是选择器要求的数据类型
// opts指定使用何种选择器
// 常用的选择器有:
// chromedp.ByID:根据id来选择元素
// chromedp.ByQuery:根据DOM.querySelector的规则选择元素
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在指定元素上触发鼠标点击事件
func Click(sel interface{}, opts ...QueryOption) Action

// chromedp.OuterHTML获取指定元素的HTML代码(包括其子元素)
// html参数用于存放返回的HTML
func OuterHTML(sel interface{}, html *string, opts ...QueryOption) Action

  

一个获取页面内容的小例子,更多例子在 https://github.com/chromedp/examples

// 获取服务列表
func GetServiceList(res *string) chromedp.Tasks {
	return chromedp.Tasks{
		// 访问服务列表
		chromedp.Navigate(ServiceListURL),
		// 等待直到body加载完毕
		chromedp.WaitReady("servicesList", chromedp.ByID),
		// 选择显示可用服务
		chromedp.Click("statusActive", chromedp.ByID),
                // 等待列表渲染
		chromedp.Sleep(2 * time.Second),
		// 获取获取服务列表HTML
		chromedp.OuterHTML("#servicesList table", res, chromedp.ByQuery),
	}
}

var html string
// cdp是chromedp实例
// ctx是创建cdp时使用的context.Context
err := cdp.Run(ctx, GetServiceList(&html) )
if err != nil {
    // 错误处理
}

// 成功取得HTML内容进行后续处理
fmt.Println(html)

  

至此golang通过chromedp(https://github.com/chromedp/chromedp)使用headless chrome进行动态网页的渲染和操作就介绍完了。

希望这篇文章能给你带来帮助,如有错误之处,欢迎交流指正。