[TOC]
Golang+chromedp+goquery 简单爬取动态数据
兵长:
胖sir,最近一段时间正在使用golang来进行开发项目,慢慢的对golang
有了一些了解,突然有一天,我想用golang来实现爬取网站上的数据,例如天气预报
,每日一句
等等,发现这些网站的数据都是javascript
动态生成,苦恼呀,不知道如何才能把网站上的动态数据
获取下来,为我所用呀,例如我抓取到动态数据之后发邮件给我哟
胖sir撩撩了自己的长发,温和的对兵长说,小伙子,golang
做应用开发效率很快的,当然爬取网站上的数据也是不在话下的哟,动态的也有动态的方法,来我给你娓娓道来
Golang的安装
此步骤主要是为了照顾没有在linux
上安装过golang的童鞋们,若自己做过安装过golang的童鞋可以直接跳过golang简单安装步骤
下载golang软件
- 【国内网站】
https://studygolang.com/dl
go语言中文网下载 go最新的安装包,根据不同的系统,可以选择windows,linux,mac
- 【可以上外网的话】访问go语言英文网站
https://docs.studygolang.com/doc/install
解压golang
tar -C /usr/local -xzf go1.16.linux-amd64.tar.gz
配置golang
将go的二进制目录添加到
PATH
环境变量vim /etc/profile export GOROOT=/usr/local/go export PATH=$PATH:$GOROOT/bin
重新导入配置
source /etc/profile
chromedp框架的使用
chromedp框架
是github
开源的,童鞋们可以放心食用,若是有想法,可以在github
上为此添砖加瓦,为开源做出自己的一份贡献
可以通过如下命令来进行下载
github.com/chromedp/chromedp
实际的代码编写
兵长,你想爬取每日一句
的网站,我给你找一个例子,如爬取这个网站http://news.iciba.com/
,我们将网站上每天都会更新的一句话爬取出来
开始编码
//获取网站上爬取的数据
func GetHttpHtmlContent(url string, selector string, sel interface{}) (string, error) {
options := []chromedp.ExecAllocatorOption{
chromedp.Flag("headless", true), // debug使用
chromedp.Flag("blink-settings", "imagesEnabled=false"),
chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`),
}
//初始化参数,先传一个空的数据
options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
c, _ := chromedp.NewExecAllocator(context.Background(), options...)
// create context
chromeCtx, cancel := chromedp.NewContext(c, chromedp.WithLogf(log.Printf))
// 执行一个空task, 用提前创建Chrome实例
chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
//创建一个上下文,超时时间为40s
timeoutCtx, cancel := context.WithTimeout(chromeCtx, 40*time.Second)
defer cancel()
var htmlContent string
err := chromedp.Run(timeoutCtx,
chromedp.Navigate(url),
chromedp.WaitVisible(selector),
chromedp.OuterHTML(sel, &htmlContent, chromedp.ByJSPath),
)
if err != nil {
logger.Info("Run err : %v\n", err)
return "", err
}
//log.Println(htmlContent)
return htmlContent, nil
}
GetHttpHtmlContent
做为一个爬取网站动态数据的接口,主要功能是爬取js
生成的动态数据(当然静态数据更是不在话下)- 第一个参数
url
即为我们需要传入的要爬取的网站地址,页面如上 第二个参数
selector
即为我们爬取的数据对应的选html择器
, 通过谷歌浏览器进入网站,按F12
->点击左上角的鼠标
->再点击我们需要爬取的数据
->就可以看到实际的html源码
(目前看到的是通过javascript
动态生成数据后的)右键点击
item-bottom
->Copy
->Copy selector
即可得到如下结果body > div.screen > div.banner > div.swiper-container-place > div > div.swiper-slide.swiper-slide-0.swiper-slide-visible.swiper-slide-active > a.item.item-big > div.item-bottom
此字符串即为
GetHttpHtmlContent
函数的第二个参数selector
第三个参数 我们暂时先写
document.querySelector("body") //从body里面获取数据
- 返回值 即为 爬取到的数据,是字符串格式的,内容是
html
如下是拓展和解释上述代码的内容
chromedp.Flag
给chromedp
设置参数,设置为无头模式 headless
,无头模式即Chrome浏览器的无GUI的命令行版浏览器,但功能上和我们平常使用的chrome没有区别,若该参数不设置为true
,则在程序运行的时候,chromedp
会拉取我们环境中的chrome浏览器,显示页面chromedp.Flag("blink-settings", "imagesEnabled=false")
设置为不显示图片htmlContent
用于接收爬取的结果,是一个字符串格式,具体内容是html
chromedp.ByJSPath
是只以什么方式进行解析,这是一个回调函数,这个参数还可以填下面几个,按需索取chromedp.ByNodeID
chromedp.BySearch
chromedp.ByID
chromedp.ByQueryAll
chromedp.ByQuery
chromedp.ByFunc
关于
chromedp
涉及的接口如下给兵长
介绍几个名字 说明 Navigate 进入某个页面 Run 运行各类操作 Screenshot 截屏 Click 模拟鼠标点击 WaitVisible 等候某元素出现 ActionFunc 执行自定义函数 SendKeys 模拟键盘输入
兵长: 使用这个框架我得到的是一串html
的字符串,我也不会解析他呀,我要如何才能找到刚才在页面上看到的每日一句
?
胖sir:别担心,我一步一步给你说,直播教学呢,看好了, 现在我们已经完成了最核心的一步了,现在数据已经获取到了,咯,我给你介绍一个神奇,goquery
就可以解决下面这一串html
的解析问题了
goquery第三方库的使用
我之前写过一个小接口,可以给你看看,兵长
goquery
也是github
开源的,童鞋们可以放心食用哦,通过如下命令在下载goquery第三方库
go get github.com/PuerkitoBio/goquery
开始编码
//得到具体的数据
func GetSpecialData(htmlContent string, selector string) (string, error) {
dom, err := goquery.NewDocumentFromReader(strings.NewReader(htmlContent))
if err != nil {
logger.Error(err)
return "", err
}
var str string
dom.Find(selector).Each(func(i int, selection *goquery.Selection) {
str = selection.Text()
})
return str, nil
}
- 第一个参数
htmlContent
就是 上面chromedp
爬取到的数据,是字符串,内容是html
第二个参数即是
html
的选择器 ,对于这个网站,这个参数可以填.chinese
,如GetSpecialData(htmlContent, ".chinese")
- 返回值就是我们要抓取的结果了
当你是在为梦想成真努力时,就不会有压力。
如下是关于goquery一些用法
主要是关于html各种选择器的写法使用方式,下面简单介绍一下种类,如果需要详细了解,可以给我留言哟
- 基于HTML Element 元素的选择器
- ID 选择器
- Class选择器
- 属性选择器
- parent > child选择器
- element + next 相邻选择器
- element~next 兄弟选择器
胖sir:兵长,我说的这些还算清楚吧,你知道怎么用了吗?
兵长:明~明白了,我还要多加练习,多多爬取一下不同的站数据看看效果
胖sir:诶,兵长刚才你说你想将数据处理完毕后,发邮件给你自己吗?
兵长:对呀,诶呀,这又是个问题。我不知道把程序放在那里呢,放在我自己电脑里面的话,我电脑每天是要关机的,我休息了,我的电脑也要跟着我休息,诶,咋办呀
胖sir:好办,这个我可以推荐你用一下 阿里云服务器
如何将自己的程序部署到阿里云服务器上
自己买一个云服务器就可以很方便的将自己的监控程序或者需要一直运行的程序放在上面,这就可以7*24小时不间断的跑了,我最近感受了一下,确实好用。具体的阿里云购买方式可以尝试扫描下面的二维码或者点击链接进行购买,亲测真的好用,如何使用和简单配置,可以给我留言获取资料。
当然,需要上述整个小案例源码的,也可以给我留言哦,让我们一起实践我们的每一个想法,一步一步往上爬。
胖sir:兵长,我需要提醒一点哦,阿里云服务器会自动把你的运行程序关闭掉了的
兵长:啊?那么你还让我买服务器,你这不是坑我吗
胖sir:别急,我推荐的肯定是好东西啦,还附带解决方案哟
screen工具
screen工具可以帮助我们将可执行程序部署到阿里云服务器上面,且能够一直不间断的运行
原理:
screen是在服务器上单独开一个进程,让他专门来执行后台任务。
具体操作:
安装
//ubuntu安装 sudo apt-get install screen //centos yum install screen
创建screen窗口
screen -S name 例如: screen -S ssh
查看进程
screen -ls
进入自己的manager
screen -r -d 自己的id 如: screen -r -d 5295
关闭screen进程
screen -S 进程名 -X quit
大家如果有需要,可以通过此链接购买阿里云服务器,目前萌新有优惠,亲测很可,别问我是谁,我是活雷锋。
https://www.aliyun.com/activity?taskCode=messenger2101&recordId=337686&usercode=&share_source=copy_link
作者:小魔童哪吒
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。