如今动态渲染的页面越来越多,爬虫们或多或少都需要用到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,可以自定义。

需要注意,chromedp在0.1.4版本中对api进行了较大的改动,因此接下来的示例中我会给出新api的用法,同时保留0.1.3及以前版本适用的例子。

// NewHeadless 创建headless chrome实例
// chromedp内部有自己的超时设置,你也可以通过ctx来设置更短的超时
func NewHeadless(ctx context.Context, starturl string) (*chromedp.CDP, error) {
// runner.Flag设置启动headless chrome时的命令行参数
// runner.URL设置启动时打开的URL
// Windows用户需要设置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
} // 默认情况chromedp会输出大量log,因为是示例所以选择屏蔽,dropChromeLogs为自定义函数,形式为func(string, ...interface{}){}
// 使用runner初始化chromedp实例
// 实例在使用完毕后需要调用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, )
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,同时也会默认启用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 方法来执行所有的操作。

在新版本中chromedp通过Run方法执行所有操作,chromedp.CDP对象被chrome.Context取代,其原型为func Run(ctx context.Context, actions ...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)

新版本的示例:

var html string
// ctxt是chromedp的实例,用于执行网页操作
err := chromedp,Run(ctxt, GetServiceList(&html))
if err != nil {
// error handle
} // 成功取得数据
fmt.Println(html)

另外新版本中关闭chrome实例的方式也有所不同:

// 释放所有资源,并等待释放结束
cancel2()
// 官方给的是chromedp,FromContext(ctxt).Wait(),但是目前没有实现Wait方法
// 因此你可以像这样
chromedp.FromContext(ctxt).Broswer.Shutdown()
chromedp.FromContext(ctxt).Allocator,Wait()

因为目前新版本还很不稳定,所以推荐使用0.1.3版本。

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

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

golang使用chrome headless获取网页内容的更多相关文章

  1. 搭建golang学习环境,并用chrome headless获取网页内容

    想用go练练手(我是win7系统,已从https://studygolang.com/dl 下载了go安装包并安装,比较简单,不详述. 但作为边民,没法go get ,又不敢用梯子,幸亏有爱心大牛们的 ...

  2. 反爬虫——使用chrome headless时一些需要注意的细节

    以前我们介绍过chrome headless的用法(https://www.cnblogs.com/apocelipes/p/9264673.html). 今天我们要稍微提一下其中一个细节. 反爬和w ...

  3. C#获取网页内容的三种方式(转)

    搜索网络,发现C#通常有三种方法获取网页内容,使用WebClient.WebBrowser或者HttpWebRequest/HttpWebResponse... 方法一:使用WebClient (引用 ...

  4. 【C#】获取网页内容及HTML解析器HtmlAgilityPack的使用

    最近经常需要下载一些东西,而这个下载地址又会经过层层跳转,每个页面上都有很多广告,烦不胜烦,所以做了一个一键获得最终下载地址的小工具.使用C#,来获取网页内容,然后通过HtmlAgilityPack获 ...

  5. C#获取网页内容的三种方式

    C#通常有三种方法获取网页内容,使用WebClient.WebBrowser或者HttpWebRequest/HttpWebResponse... 方法一:使用WebClient (引用自:http: ...

  6. C#获取网页内容 (WebClient、WebBrowser和HttpWebRequest/HttpWebResponse)

    获取网页数据有很多种方式.在这里主要讲述通过WebClient.WebBrowser和HttpWebRequest/HttpWebResponse三种方式获取网页内容. 这里获取的是包括网页的所有信息 ...

  7. go golang 判断base64数据 获取随机字符串 截取字符串

    go golang 判断base64数据 获取随机字符串 截取字符串 先少写点,占个坑,以后接着加. 1,获取指定长度随机字符串 func RandomDigits(length int) strin ...

  8. 定义一个方法get_page(url),url参数是需要获取网页内容的网址,返回网页的内容。提示(可以了解python的urllib模块)

    定义一个方法get_page(url),url参数是需要获取网页内容的网址,返回网页的内容.提示(可以了解python的urllib模块) import urllib.request def get_ ...

  9. chrome headless 无头浏览器 应用

    1. 根据html生成pdf chrome.exe --headless --disable-gpu --print-to-pdf ...../index.html 2. puppeteer --- ...

随机推荐

  1. 记一下vue.js事件的修饰等问题

    在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求.尽管我们可以在 methods 中轻松实现这点,但更好的方式是 ...

  2. iOS开发之ReactiveCocoa下的MVVM

    最近工作比较忙,但还是出来更新博客了,今天给大家分享一些ReactiveCocoa以及MVVM的一些东西,干活还是比较足的.在之前发表过一篇博文,名字叫做<iOS开发之浅谈MVVM的架构设计与团 ...

  3. Spring Boot使用AOP实现REST接口简易灵活的安全认证

    我们继续上一篇文章的分析,本文将通过AOP的方式实现一个相对更加简易灵活的API安全认证服务. 我们先看实现,然后介绍和分析AOP基本原理和常用术语. 一.Authorized实现 1.定义注解 pa ...

  4. ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承

    在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...

  5. HNOI2019退役记

    退役 警告. 今年虽然我没有变强, 但是还是比去年强一点(去年树形dp都不会). Day0 明天就是省选了,晚上22:13还没有睡觉,真的是状态不好. 打了一下LCT的板子,发现终于理解了...(这叫 ...

  6. IM群聊消息的已读回执功能该怎么实现?

    本文引用了架构师之路公众号作者沈剑的文章,内容有改动,感谢原作者. 1.前言 我们平时在使用即时通讯应用时候,每当发出一条聊天消息,都希望对方尽快看到,并尽快回复,但对方到底有没有真的看到?我却并不知 ...

  7. 微信小程序新闻信息列表展示

    微信小程序信息展示列表 wxml <!-- 轮播图 --> <view class='haibao' bindtap="seeDetail" id="{ ...

  8. 应用监控CAT之cat-home源码阅读(三)

    上两章从点到点讲了,cat-client  到  cat-consumer 的请求处理过程,但是怎么样让我们监控给人看到呢?那么就需要一个展示的后台了,也就是本章要讲的 cat-home 模块 ! 带 ...

  9. CAS单点登录原理简单介绍

    1. SSO简介 1.1 单点登录定义 单点登录(Single sign on),英文名称缩写SSO,SSO的意思就是在多系统的环境中,登录单方系统,就可以在不用再次登录的情况下访问相关受信任的系统. ...

  10. vue webpack配置解决跨域问题

    现在基本项目都是实行前后端分离的原则,不管是ng 或者是vue 在开发中都无法避免跨域的这个问题 本人刚上手第一个vue项目,在调用api的时候出现了跨域的这个问题 这是封装好一个简单的post 请求 ...