47

golang使用chrome+Selenium2.0+ChromeDriver使用总结

 5 years ago
source link: https://studygolang.com/articles/15241?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前段时间项目临时需要做一个数据爬虫,因为我不会用python,真tmd尴尬,就用golang来写,最后我还tmd没有用爬虫框架,哎,接下来写写一下做这个爬虫中使用到的一些技术,因为时间紧张,所以要是中间有问题请大佬指正。

这是一个公众号爬虫,主要是为了爬取头条号,熊掌号,大鱼号等公众号。
   
对于一般的使用API的公众号其实是要稍微简单的,我们只需要模拟请求他的API就可以了,但是对于熊掌号,大鱼号这种,因为他是没有直接的入口的(反正我暂时没有找到,要是大佬有找到的,恳请大佬不吝赐教)。然后就是对于头条号这种了,因为头条号是采用接口的形式,**但是** ,他是有接口签名的,并且这个签名还贼tmd难,所以我们需要直接调用浏览器中的命令来获取签名。

要是文章中有什么地方说错了,请大佬赐教,感谢

1.一些基本的概念:

chrome-Headless: 顾明思议,是一种无浏览器窗口的模式,是Google 自己出的无头浏览器模式, Google 针对 Chrome 浏览器 59版 新增加的一种模式,可以让你不打开UI界面的情况下使用 Chrome 浏览器

ChromeDriver :WebDriver是一个开源工具,用于在许多浏览器上自动测试webapps。 ChromeDriver 是 google 为网站开发人员提供的自动化测试接口,它是 selenium2 和 chrome浏览器 进行通信的桥梁。具体 webDriver和ChromeDriver的工作流程 请移步。

后面我还会再在代码里仔细讲一下selenium和webDriver,ChromeDriver这三者之间的工作流程

废话不多说,开始干:

2.安装ChromeDriver

centos上安装:

在/etc/yum.repos.d/
下编辑文件 google-chrome.repo
     [google-chrome]
        name=google-chrome
        baseurl=http://dl.google.com/linux/chrome/rpm/stable/x86_64
        enabled=1
        gpgcheck=1
        gpgkey=https://dl.google.com/linux/linux_signing_key.pub
  使用yum -y install google-chrome-stable --nogpgcheck
  这里我安装的是chrome的最新版本,

bVbhMZs?w=777&h=375

安装依赖

yum install \

ipa-gothic-fonts \

xorg-x11-fonts-100dpi \

xorg-x11-fonts-75dpi \

xorg-x11-utils \

xorg-x11-fonts-cyrillic \

xorg-x11-fonts-Type1 \

xorg-x11-fonts-misc -y

安装完毕之后,我们测试时候能运行

google-chrome-stable --no-sandbox --headless --disable-gpu --screenshot https://www.suning.com/

bVbhM0W?w=1333&h=139

显示这样说明差不多成功了

接着我们安装chromeDriver,首先我们需要知道我们应该chrome和chromeDriver的 版本对比 ,然后去 下载 对应的版本

3.Golang代码

func main() {

    const (
        seleniumPath = `D:\workSoftware\chormdriver\chromedriver.exe`
        port            = 9515
    )

    //如果seleniumServer没有启动,就启动一个seleniumServer所需要的参数,可以为空,示例请参见https://github.com/tebeka/selenium/blob/master/example_test.go
    opts := []selenium.ServiceOption{}
    //opts := []selenium.ServiceOption{
    //    selenium.StartFrameBuffer(),           // Start an X frame buffer for the browser to run in.
    //    selenium.GeckoDriver(geckoDriverPath), // Specify the path to GeckoDriver in order to use Firefox.
    //}

    //selenium.SetDebug(true)
    service, err := selenium.NewChromeDriverService(seleniumPath, port, opts...)
    if nil != err {
        fmt.Println("start a chromedriver service falid", err.Error())
        return
    }
    //注意这里,server关闭之后,chrome窗口也会关闭
    defer service.Stop()

    //链接本地的浏览器 chrome
    caps := selenium.Capabilities{
        "browserName": "chrome",
    }

    //禁止图片加载,加快渲染速度
    imagCaps := map[string]interface{}{
        "profile.managed_default_content_settings.images": 2,
    }
    chromeCaps := chrome.Capabilities{
        Prefs: imagCaps,
        Path:  "",
        Args: []string{
            //"--headless", // 设置Chrome无头模式,在linux下运行,需要设置这个参数,否则会报错
            //"--no-sandbox",
            "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", // 模拟user-agent,防反爬
        },
    }
    //以上是设置浏览器参数
    caps.AddChrome(chromeCaps)


    // 调起chrome浏览器
    w_b1, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
    if err != nil {
        fmt.Println("connect to the webDriver faild", err.Error())
        return
    }
    //关闭一个webDriver会对应关闭一个chrome窗口
    //但是不会导致seleniumServer关闭
    defer w_b1.Quit()
    err = w_b1.Get("https://zhuanlan.zhihu.com/p/37752206")
    if err != nil {
        fmt.Println("get page faild", err.Error())
        return
    }



    // 重新调起chrome浏览器
    w_b2, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", port))
    if err != nil {
        fmt.Println("connect to the webDriver faild", err.Error())
        return
    }
    defer w_b2.Close()
    //打开一个网页
    err = w_b2.Get("https://www.toutiao.com/")
    if err != nil {
        fmt.Println("get page faild", err.Error())
        return
    }
    //打开一个网页
    err = w_b2.Get("https://www.baidu.com/")
    if err != nil {
        fmt.Println("get page faild", err.Error())
        return
    }
    //w_b就是当前页面的对象,通过该对象可以操作当前页面了
    //........
    time.Sleep(5* time.Minute)
    return
}

在1基本概念中,我说道 selenium和webDriver,ChromeDriver三者之间的关系 ,现在我通过代码详细说一下

通过运行上面的代码,并查看系统进程 tasklist | find "chrome" ,

我们发现,我们起了两个webDriver,w_b1,和w_b2,
其中w_b2打开了两个网页,但是最终网页是baidu首页,说明浏览器窗口个数和webDerver有关。
 
我们查看本地线程:

bVbhNdT?w=920&h=292

发现只有一个chromeDriver.exe,说明
chromeDriver.exe和chrome.exe是一对多的关系

所以他们三者的运行机制是:

  1. 代码 selenium.NewChromeDriverService(seleniumPath, port, opts...)打开一个chromeDriver进程
  2. 一个chromeDriver进程会管理很多chrome进程
  3. 一个webDriver实例对应一个浏览器窗口,实例的数量对应窗口的数量。
  4. selenium是通过开启一个chromeDriver进程来实现对浏览器的操作和管理的

参考内容: https://www.jianshu.com/p/31c...

https://juejin.im/entry/5add6fd3f265da0b7d0afafd
    https://github.com/tebeka/selenium/blob/master/example_test.go
       https://www.jianshu.com/p/31c8c9de8fcd
   https://www.jianshu.com/p/31c8c9de8fcd

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK