1. Webdriver
WebDriver는 사용자 에이전트를 검사하고 제어할 수 있는 원격 제어 인터페이스입니다. 프로세스 외부의 프로그램이 웹 브라우저의 동작을 원격으로 지시할 수 있어 웹 자동화를 가능하게 합니다. 웹 문서에서 DOM을 발견하고 조작하고 사용자 에이전트의 동작을 제어하기 위한 인터페이스 세트가 제공됩니다. 따라서 주로 웹 제작자가 별도의 제어 프로세스에서 사용자 에이전트를 자동화하는 테스트를 작성하는 데 사용하지만, 보통 인공지능 학습을 위한 데이터셋 준비 등 웹 크롤링에 자주 사용됩니다.(페이지 스크립트 구동이 필요한 경우 html 파싱만으로 읽을 수 없는 요소들이 있기 때문)
셀레니움이 웹드라이버 API를 제공하고 있으며, go에서도 셀레니움 라이브러리가 있지만 셀레니움 라이브러리를 개발하신 분이 현재는 관리를 중단하신 상태이기 때문에 셀레니움이 아닌 다른 방법으로 webdriver를 사용하는 방법을 소개합니다.
2. Go webdriver
1) Go webdriver 설치
https://github.com/fedesog/webdriver
go 에는 go webdriver 라이브러리를 통해 셀레니움을 사용하는 것보다 빠르고 간편하게 웹 드라이버를 운용할 수 있도록 하고 있습니다. 다른 라이브러리와 마찬가지로 아래 명령어를 입력해 설치하시면 됩니다.
$ go get github.com/fedesog/webdriver
2) Go webdriver 사용
go 의 가장 큰 장점은 Documentation이 명확하고 깔끔하게 정리되어 있다는 점인데, webdriver 라이브러리 역시 그렇습니다. 본 글에서는 ChromeDriver를 활용한 기본적인 사용법에 대해서만 다루니 필요에 따라 공식 문서를 참고하시기 바랍니다.
a. 웹드라이버 실행
func main(url string, driverpath string) {
chromedriver := webdriver.NewChromeDriver(driverpath)
driverRunErr := chromedriver.Start()
checkErr(driverRunErr)
...
}
var Name NewChromeDriver(drivepath)
는 사용할 크롬 드라이버의 위치를 알려주고 초기화하는 기능을 합니다. 크롬 드라이버를 선언하고 나면 Name.Start()
를 통해 크롬드라이버를 실행할 수 있습니다.
b. 세션 실행
func main(url string, driverpath string) {
...
desired := webdriver.Capabilities{"Platform": "Linux"}
required := webdriver.Capabilities{}
session, err := chromedriver.NewSession(desired, required)
checkErr(err)
openURLerr := session.Url(url)
checkErr(openURLerr)
}
실행된 크롬드라이버가 실제 url을 읽어 동작할 수 있도록 Capabilities를 입력하고 drivername.NewSession
을 통해 세션을 열어줍니다. 이제 이 세션은 session.Url(string)
을 통해 특정 url페이지를 열 수 있습니다.
세션의 구조는 아래와 같이 구성되어 있습니다.
//Capabilities is a map that stores capabilities of a session.
type Capabilities map[string]interface{}
//A session.
type Session struct {
Id string
Capabilities Capabilities
wd WebDriver
}
c. 페이지 소스(html) 추출
웹드라이버를웹 드라이버를 통해 열린 웹페이지의 html source를 가져오는 것 또한 가능합니다. 웹사이트 크롤링을 시도할 때 크롤링이 실패하는 이유 중 하나가 일반적인 html 파싱으로는 페이지 스크립트가 실행되지 않기 때문입니다. 하지만 웹 드라이버를 사용하는 경우 실제 웹사이트에 접속하여 스크립트를 실행시키기 때문에 온전한 정보를 수집하는 게 가능합니다.
func main(url string, driverpath string) {
...
resp, err := session.Source()
checkErr(err)
htmlNode, err := html.Parse(strings.NewReader(resp))
checkErr(err)
}
session.Source()
는 세션에서 읽어드린 url의 html source를 string 형태로 return 합니다.
읽어드린 페이지 소스를 사용하기위해 strings.NewReader(htmlstring)
를 통해 string -> html.Node 형태로 바꿔줍니다.
이를 net/html을 이용해 파싱해주면 스크립트가 모두 동작한 상태의 웹 페이지 소스를 얻을 수 있습니다.
d. 웹드라이버 종료
func main() {
...
defer session.Delete()
defer chromedriver.Stop()
}
session.Delete()
는 현재 열려있는 세션만 종료하고, 크롬 드라이버는 계속 켜져있게 됩니다. 크롬 드라이버를 완전히 종료하실 때는 driver.Stop(
)하면 됩니다.