热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

go语言怎么使用Chromedp实现二维码登陆

本文小编为大家详细介绍“go语言怎么使用Chromedp实现二维码登陆”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言怎么使用Chromedp实现二

本文小编为大家详细介绍“go语言怎么使用Chromedp实现二维码登陆”,内容详细,步骤清晰,细节处理妥当,希望这篇“go语言怎么使用Chromedp实现二维码登陆”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

1 Chromedp是什么

chromedp是一个更快、更简单的Golang库用于调用支持Chrome DevTools协议的浏览器,同时不需要额外的依赖(例如Selenium和PhantomJS)

Chrome和Golang都与Google有着相当密切的关系,而Chrome DevTools其实就是Chrome浏览器按下F12之后的控制终端

2 为什么不使用Selenium

对于Golang开发来说,使用chromedp更为便捷,因为它仅仅需要Chrome浏览器而并不需要依赖ChromeDriver,省去了依赖问题,有助于自动化的构建和多平台架构的迁移

3 文章解决了什么需求

  • 如何使用chromedp进行二维码登陆

  • 如何将二维码展示在无图形化的终端上(makiuchi-d/gozxing解码 skip2/ go-qrcode编码)

  • 如何保存COOKIEs实现短时间免登陆

网站会更新,文章不保证更新,请务必学会举一反三

4.如何使用chromedp进行二维码登陆

4.1 安装chromedp

  • 下载并安装Chrome浏览器

  • 创建Golang项目,开启Go Module(在项目目录下使用终端输入go mod init)

  • 在项目目录下使用终端输入:

go get -u github.com/chromedp/chromedp

(如果有依赖问题请删除-u)

4.2 尝试打开网站

(以金山文档https://account.wps.cn/为例)

1.重新设置chromedp使用"有头"的方式打开,以便于我们进行debug

func main(){
    // chromdp依赖context上限传递参数
	ctx, _ := chromedp.NewExecAllocator(
		context.Background(),
		// 以默认配置的数组为基础,覆写headless参数
		// 当然也可以根据自己的需要进行修改,这个flag是浏览器的设置
		append(
			chromedp.DefaultExecAllocatorOptions[:],
			chromedp.Flag("headless", false),
		)...,
	)
}

2.创建chromedp上下文对象

func main(){
    // chromdp依赖context上限传递参数
    ...
    // 创建新的chromedp上下文对象,超时时间的设置不分先后
    // 注意第二个返回的参数是cancel(),只是我省略了
	ctx, _ = context.WithTimeout(ctx, 30*time.Second)
	ctx, _ = chromedp.NewContext(
		ctx,
		// 设置日志方法
		chromedp.WithLogf(log.Printf),
	)
	// 通常可以使用 defer cancel() 去取消
	// 但是在Windows环境下,我们希望程序能顺带关闭掉浏览器
	// 如果不希望浏览器关闭,使用cancel()方法即可
	// defer cancel()
	// defer chromedp.Cancel(ctx)
}

3.执行自定义的任务

func main(){
    // chromdp依赖context上限传递参数
    ...
    // 创建新的chromedp上下文对象,超时时间的设置不分先后
    // 注意第二个返回的参数是cancel(),只是我省略了
    ...
    // 执行我们自定义的任务 - myTasks函数在第4步
	if err := chromedp.Run(ctx, myTasks()); err != nil {
		log.Fatal(err)
		return
	}
}

4.至此程序的初始化过程已经完成,接下来就是任务——打开登陆页面

// 自定义任务
func myTasks() chromedp.Tasks {
	return chromedp.Tasks{
		// 1. 打开金山文档的登陆界面
		chromedp.Navigate(loginURL),
	}
}

5.运行一下程序,可以看到Chrome被打开,同时访问了我们指定的网站

go语言怎么使用Chromedp实现二维码登陆

4.3 获取二维码(点击过程)

1.需要点击微信登陆按钮,先找到按钮的选择器,右键按钮并在菜单中点击检查,然后可以看到按钮的元素

go语言怎么使用Chromedp实现二维码登陆

2.右键元素打开菜单找到copy下的copy selector,即获取到选择器

go语言怎么使用Chromedp实现二维码登陆

3.我们尝试点击微信登陆按钮,发现还需要点击一下确认,重复上述步骤获取确认按钮的选择器

go语言怎么使用Chromedp实现二维码登陆

4.用代码执行上述点击步骤

// 自定义任务
func myTasks() chromedp.Tasks {
	return chromedp.Tasks{
		// 1. 打开金山文档的登陆界面
		chromedp.Navigate(loginURL),
		// 2. 点击微信登陆按钮
		// #wechat > span:nth-child(2)
		chromedp.Click(`#wechat > span:nth-child(2)`),
		// 3. 点击确认按钮
		// #dialog > div.dialog-wrapper > div > div.dialog-footer > div.dialog-footer-ok
		chromedp.Click(`#dialog > div.dialog-wrapper > div > div.dialog-footer > div.dialog-footer-ok`),
	}
}

5.运行程序即可直达二维码展示界面

go语言怎么使用Chromedp实现二维码登陆

6.用同样的方式,获取二维码图片的选择器

go语言怎么使用Chromedp实现二维码登陆

7.用代码实现获取二维码

有两点需要注意,第一是二维码有加载过程,第二是二维码是元素渲染,

我们需要用截图的方式获取(也可以用js来获取对应的href并下载,但是为了照顾小白,选择最简单的)

func myTasks() chromedp.Tasks {
	return chromedp.Tasks{
		// 1. 打开金山文档的登陆界面
		...
		// 2. 点击微信登陆按钮
		...
		// 3. 点击确认按钮
		...
		// 4. 获取二维码
		// #wximport
		getCode(),
	}
}
func getCode() chromedp.ActionFunc {
	return func(ctx context.Context) (err error) {
		// 1. 用于存储图片的字节切片
		var code []byte
		// 2. 截图
		// 注意这里需要注明直接使用ID选择器来获取元素(chromedp.ByID)
		if err = chromedp.Screenshot(`#wximport`, &code, chromedp.ByID).Do(ctx); err != nil {
			return
		}
		// 3. 保存文件
		if err = ioutil.WriteFile("code.png", code, 0755); err != nil {
			return
		}
		return
	}
}

8.执行程序即可发现目录下已经存储了二维码图片文件,我们可以通过扫描此二维码进行登陆,与浏览器上扫描为同一种效果

go语言怎么使用Chromedp实现二维码登陆

5. 如何将二维码展示在无图形化的终端上

(与chromedp无关,属于额外内容)

1.在上述步骤中,我们已经获取了二维码,接下来我们需要在终端显示二维码,首先是解码,这里使用gozxing库

func printQRCode(code []byte) (err error) {
	// 1. 因为我们的字节流是图像,所以我们需要先解码字节流
	img, _, err := image.Decode(bytes.NewReader(code))
	if err != nil {
		return
	}
	// 2. 然后使用gozxing库解码图片获取二进制位图
	bmp, err := gozxing.NewBinaryBitmapFromImage(img)
	if err != nil {
		return
	}
	// 3. 用二进制位图解码获取gozxing的二维码对象
	res, err := qrcode.NewQRCodeReader().Decode(bmp, nil)
	if err != nil {
		return
	}
	return
}

2.然后重新编码来输出二维码到终端,这里使用go-qrcode库

// 请注意import的库发生了重名
import (
	"github.com/makiuchi-d/gozxing"
	"github.com/makiuchi-d/gozxing/qrcode"
	goQrcode "github.com/skip2/go-qrcode"
)
func printQRCode(code []byte) (err error) {
	// 1. 因为我们的字节流是图像,所以我们需要先解码字节流
	...
	// 2. 然后使用gozxing库解码图片获取二进制位图
	...
	// 3. 用二进制位图解码获取gozxing的二维码对象
	...
	// 4. 用结果来获取go-qrcode对象(注意这里我用了库的别名)
	qr, err := goQrcode.New(res.String(), goQrcode.High)
	if err != nil {
		return
	}
	// 5. 输出到标准输出流
	fmt.Println(qr.ToSmallString(false))
	return
}

3.修改我们第二步的过程

func getCode() chromedp.ActionFunc {
	return func(ctx context.Context) (err error) {
		// 1. 用于存储图片的字节切片
		...
		// 2. 截图
		// 注意这里需要注明直接使用ID选择器来获取元素(chromedp.ByID)
		...
		// 3. 把二维码输出到标准输出流
		if err = printQRCode(code); err != nil {
			return err
		}
		return
	}
}

3.运行程序即可查看效果

go语言怎么使用Chromedp实现二维码登陆

6. 如何保存COOKIEs实现短时间免登陆

1.在上述过程中,我们可以通过二维码扫描登陆,网站会在登陆之后进行跳转,跳转后我们需要保存COOKIEs来维持我们的登录状态,代码实现如下

// 保存COOKIEs
func saveCOOKIEs() chromedp.ActionFunc {
	return func(ctx context.Context) (err error) {
		// 等待二维码登陆
		if err = chromedp.WaitVisible(`#app`, chromedp.ByID).Do(ctx); err != nil {
			return
		}
		// COOKIEs的获取对应是在devTools的network面板中
		// 1. 获取COOKIEs
		COOKIEs, err := network.GetAllCOOKIEs().Do(ctx)
		if err != nil {
			return
		}
		// 2. 序列化
		COOKIEsData, err := network.GetAllCOOKIEsReturns{COOKIEs: COOKIEs}.MarshalJSON()
		if err != nil {
			return
		}
		// 3. 存储到临时文件
		if err = ioutil.WriteFile("COOKIEs.tmp", COOKIEsData, 0755); err != nil {
			return
		}
		return
	}
}

2.获取到COOKIEs之后,我们需要在程序运行时将COOKIEs从临时文件中加载到浏览器中

// 加载COOKIEs
func loadCOOKIEs() chromedp.ActionFunc {
	return func(ctx context.Context) (err error) {
		// 如果COOKIEs临时文件不存在则直接跳过
		if _, _err := os.Stat("COOKIEs.tmp"); os.IsNotExist(_err) {
			return
		}
		// 如果存在则读取COOKIEs的数据
		COOKIEsData, err := ioutil.ReadFile("COOKIEs.tmp")
		if err != nil {
			return
		}
		// 反序列化
		COOKIEsParams := network.SetCOOKIEsParams{}
		if err = COOKIEsParams.UnmarshalJSON(COOKIEsData); err != nil {
			return
		}
		// 设置COOKIEs
		return network.SetCOOKIEs(COOKIEsParams.COOKIEs).Do(ctx)
	}
}

3.通过上述两步我们已经可以保持登陆状态,然后我们需要检查一下是否成功,这里调用浏览器执行js脚本获取当前页面的网址,判断是否已经个人中心页面,如果为真,则停止操作

// 检查是否登陆
func checkLoginStatus() chromedp.ActionFunc {
	return func(ctx context.Context) (err error) {
		var url string
		if err = chromedp.Evaluate(`window.location.href`, &url).Do(ctx); err != nil {
			return
		}
		if strings.Contains(url, "https://account.wps.cn/usercenter/apps") {
			log.Println("已经使用COOKIEs登陆")
			chromedp.Stop()
		}
		return
	}
}

4.最终重新设置我们的浏览器任务即可

// 自定义任务
func myTasks() chromedp.Tasks {
	return chromedp.Tasks{
		// 0. 加载COOKIEs <-- 变动
		loadCOOKIEs(),
		// 1. 打开金山文档的登陆界面
		...
		// 判断一下是否已经登陆  <-- 变动
		checkLoginStatus(),
		// 2. 点击微信登陆按钮
		// #wechat > span:nth-child(2)
		...
		// 3. 点击确认按钮
		// #dialog > div.dialog-wrapper > div > div.dialog-footer > div.dialog-footer-ok
		...
		// 4. 获取二维码
		// #wximport
		...
		// 5. 若二维码登录后,浏览器会自动跳转到用户信息页面  <-- 变动
		saveCOOKIEs(),
	}
}

5.我们使用已经登陆的COOKIEs运行程序可以发现我们成功跳过登陆过程

go语言怎么使用Chromedp实现二维码登陆

读到这里,这篇“go语言怎么使用Chromedp实现二维码登陆”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程笔记行业资讯频道。


推荐阅读
  • 利用爬虫技术抓取数据,结合Fiddler与Postman在Chrome中的应用优化提交流程
    本文探讨了如何利用爬虫技术抓取目标网站的数据,并结合Fiddler和Postman工具在Chrome浏览器中的应用,优化数据提交流程。通过详细的抓包分析和模拟提交,有效提升了数据抓取的效率和准确性。此外,文章还介绍了如何使用这些工具进行调试和优化,为开发者提供了实用的操作指南。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 如何撰写初级和高级前端开发者的专业简历
    如何撰写初级和高级前端开发者的专业简历 ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
  • 【Linux进阶指南】第一阶段第三课:体验与部署Ubuntu系统
    在正式踏上Linux学习之旅之前,本课程将引导你深入体验和部署Ubuntu系统。通过详细的操作步骤和实践演练,你将掌握Ubuntu的基本安装、配置及常用命令,为后续的进阶学习打下坚实的基础。此外,课程还将介绍如何解决常见问题和优化系统性能,帮助你更加高效地使用Ubuntu。 ... [详细]
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 全面解析JavaScript代码注释技巧与标准规范
    在Web前端开发中,JavaScript代码的可读性和维护性至关重要。本文将详细介绍如何有效地使用注释来提高代码的可读性,并探讨JavaScript代码注释的最佳实践和标准规范。通过合理的注释,开发者可以更好地理解和维护复杂的代码逻辑,提升团队协作效率。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 如何撰写适应变化的高效代码:策略与实践
    编写高质量且适应变化的代码是每位程序员的追求。优质代码的关键在于其可维护性和可扩展性。本文将从面向对象编程的角度出发,探讨实现这一目标的具体策略与实践方法,帮助开发者提升代码效率和灵活性。 ... [详细]
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • 提升 Kubernetes 集群管理效率的七大专业工具
    Kubernetes 在云原生环境中的应用日益广泛,然而集群管理的复杂性也随之增加。为了提高管理效率,本文推荐了七款专业工具,这些工具不仅能够简化日常操作,还能提升系统的稳定性和安全性。从自动化部署到监控和故障排查,这些工具覆盖了集群管理的各个方面,帮助管理员更好地应对挑战。 ... [详细]
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 大家好,全新的技术专栏《从零开始掌握容器云网络实战》正式上线。该专栏将系统地介绍容器云网络的基础知识、核心技术和实际应用案例,帮助读者全面理解和掌握容器云网络的关键技术与实践方法。 ... [详细]
author-avatar
D萳飝赝_870
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有