【在主画面加入捷径】
       
【选择语系】
繁中 简中

[Selenium][网络爬虫] 程序设计教学:如何使用 Go (Golang) 操作浏览器

WEB
【赞助商连结】

    前言

    虽然 Selenium 并未提供给 Go (golang) 使用的官方 binding,透过 tebeka/selenium 这类社群套件,同样可以用来操作 Selenium (或 WebDriver)。目前 tebeka/selenium 的范例偏少,大概只能看官方 API 来学如何使用。本文以两个 Hello World 等级范例,分别来看如何透过 Selenium (或 WebDriver) 操作浏览器。

    使用 Go (golang) 最大的好处,在于可以保护程序代码;因 Go (golang) 是编译语言,无法直接透过反组译得到源代码。相对来说,使用先前介绍的 Java 来写 Selenium 网络爬虫没有保护源代码的功能,透过 Java 的 IDE 可以轻易地还原至原本的程序代码。不过,tebeka/selenium 这类社群套件的文件相对缺乏,只能看少数的范例和 API 文件慢慢去学该套件的使用方式。

    tebeka/selenium 的作者默认的使用平台是 GNU/Linux 等类 Unix 系统 (参考此 issue);不过,经笔者实测,其实在 Windows 上也可以执行,只是要去掉类 Unix 系统特有的功能,像是 framebuffer。理论上,Selenium 可以支援所有的主流浏览器,但 tebeka/selenium 目前仅支援 Chrome 和 Firefox,故我们的范例会分别操作这两个浏览器。

    如何使用 Go (Golang) 透过 WebDriver 操作 Chrome

    在本范例中,我们不透过 Selenium,而直接透过 Chrome Driver 操作 Chrome 浏览器:

    package main
    
    import (
    	"fmt"
    	"os"
    	"time"
    
    	"github.com/tebeka/selenium"
    )
    
    const (
    	port = 8080
    )
    
    func main() {
    	opts := []selenium.ServiceOption{
    		// Enable fake XWindow session.
    		// selenium.StartFrameBuffer(),
    		selenium.Output(os.Stderr), // Output debug information to STDERR
    	}
    
    	// Enable debug info.
    	// selenium.SetDebug(true)
    	service, err := selenium.NewChromeDriverService("chromedriver", port, opts...)
    	if err != nil {
    		panic(err)
    	}
    	defer service.Stop()
    
    	caps := selenium.Capabilities{"browserName": "chrome"}
    	wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://127.0.0.1:%d/wd/hub", port))
    	if err != nil {
    		panic(err)
    	}
    	defer wd.Quit()
    
    	wd.Get("https://tw.yahoo.com")
    
    	time.Sleep(5 * time.Second)
    }

    一开始要先建立服务 (service),这个服务会在背景执行。接着,会建立连线 (remote),一并建立 wd (webdriver) 物件,之后实际的动作会透过 wd 物件来执行。由于我们这个范例仅是展示如何开启浏览器,故我们只简单拜访一下 Yahoo 台湾网站,没有做其他动作。

    如果开启 framebuffer,这只程序会藉由 xvfb 软件开启虚拟萤幕,这时候 Chrome 会在虚拟萤幕中执行,不会看到 Chrome 的画面。这个方式比用 headless 模式更好,因为 headless 模式会被一些网站侦测出来,但虚拟萤幕视为真实的桌面环境,不算 headless 模式。但 framebuffer 是类 Unix 系统限定的功能,在 Windows 上要记得关掉。

    如何使用 Go (Golang) 透过 Selenium 操作 Firefox

    在操控 Firefox 时,除了需要 GeckoDriver 外,还要 Selenium 服务器 (JAR 档),故系统上要有 Java 环境。范例程序代码如下:

    package main
    
    import (
    	"fmt"
    	"os"
    	"time"
    
    	"github.com/tebeka/selenium"
    )
    
    const (
    	seleniumPath    = "selenium-server-standalone-3.141.59.jar"
    	geckoDriverPath = "geckodriver"
    	port            = 8080
    )
    
    func main() {
    	opts := []selenium.ServiceOption{
    		// Enable fake XWindow session.
    		// selenium.StartFrameBuffer(),
    		selenium.GeckoDriver(geckoDriverPath),
    		selenium.Output(os.Stderr), // Output debug information to STDERR
    	}
    
    	// Enable debug info.
    	// selenium.SetDebug(true)
    	service, err := selenium.NewSeleniumService(seleniumPath, port, opts...)
    	if err != nil {
    		panic(err)
    	}
    	defer service.Stop()
    
    	caps := selenium.Capabilities{"browserName": "firefox"}
    	wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://127.0.0.1:%d/wd/hub", port))
    	if err != nil {
    		panic(err)
    	}
    	defer wd.Quit()
    
    	wd.Get("https://tw.yahoo.com")
    
    	time.Sleep(5 * time.Second)
    }

    为什么需要额外的 Selenium 服务器呢?据 tebeka/selenium 开发者述,因为 GeckoDriver 的迭代较快,直接操作 GeckoDriver 易因 API 更动造成错误,故透过 Selenium 服务器间接使用 GeckoDriver 操控 Firefox。

    除了使用的浏览器相异,这两只程序的行为基本上是相同的,读者可以自行阅读程序代码。

    结语

    这两只程序只是连线到 Yahoo 台湾网站,并没有进行复杂的网页操作。我们这两只程序的目的在于确认开发环境是否正常运作,相当于 Hello World 程序。经笔者实测,除了 framebuffer 外,这些程序在 Windows 或类 Unix 系统皆可顺利运行。日后有机会,或许我们会再用 tebeka/selenium 套件展示一些更复杂的应用。

    【赞助商连结】
    TAGS: SELENIUM