借助agouti库我们可以在golang下实现对动态网页的爬取。
安装:
go get -u -v github.com/sclevine/agouti
package main
import (
"fmt"
"math/rand"
"time"
"github.com/sclevine/agouti"
)
var UserAgentList = [...]string{
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) " +
"Chrome/14.0.835.163 Safari/535.1",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; " +
"SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.41 Safari/535.1 " +
"QQBrowser/6.9.11079.201",
}
func getRandUA() string {
rand.Seed(time.Now().UnixNano())
rd := rand.Intn(len(UserAgentList) - 1)
return UserAgentList[rd]
}
func main() {
capabilities := agouti.NewCapabilities()
//使用随机的ua头
capabilities["phantomjs.page.settings.userAgent"] = getRandUA()
//是否加载图片
capabilities["phantomjs.page.settings.loadImages"] = false
capabilities["phantomjs.page.settings.resourceTimeout"] = 30
capabilities["phantomjs.page.settings.disk-cache"] = false
//phantomjs 不支持gzip
capabilities["phantomjs.page.customHeaders.accept-encoding"] = "deflate, br"
capabilities["phantomjs.page.settings.clearMemoryCaches"] = true
capabilitiesOption := agouti.Desired(capabilities)
dr := agouti.PhantomJS(capabilitiesOption)
// driver启动超时时间
dr.Timeout = time.Second*20
// 启动phantomjs
if err := dr.Start(); err != nil {
fmt.Printf("failed to start driver, err:%s", err.Error())
return
}
defer dr.Stop()
// 打开一个新的页面
page, err := dr.NewPage()
if err != nil {
fmt.Printf("failed to open page, err:%s", err.Error())
return
}
defer page.CloseWindow()
// 网页加载超时,单位毫秒
page.SetPageLoad(10000)
err = page.Navigate("http://www.toutiao.com")
if err != nil {
fmt.Printf("failed to navigate, err:%s ", err.Error())
return
}
fmt.Println(page.HTML())
//截图
page.Screenshot(“./toutiao.png”)
}
使用phantomjs 有几个需要注意的点:
capabilities[“phantomjs.page.settings.loadImages”] = true
具体参考这个讨论: https://github.com/ariya/phantomjs/issues/12903
一个phantomjs实例长期运行不关闭会造成内存泄漏,目前应该没办法解决。 所以,建议一个实例使用后马上关闭它, 可以避免内存泄漏问题。
启动phantomjs实例去做请求,可能会因为启动driver超时造成这次请求失败。所以,这种情况最好还是处理一下,比如找个地方把任务缓存一下,再做一次。
phantomjs进程可能无法有效退出, 建议程序退出时强制杀死进行清理。
总之: phantomjs会有很多的bug,小心使用。
optionList := []string{
"--headless",
"--window-size=1000,900",
"--incognito", //隐身模式
"--blink-settings=imagesEnabled=true",
"--no-default-browser-check",
"--ignore-ssl-errors=true",
"--ssl-protocol=any",
"--no-sandbox",
"--disable-breakpad",
"--disable-gpu",
"--disable-logging",
"--no-zygote",
"--allow-running-insecure-content",
}
userAgent := "--user-agent=" + getRandUA()
optionList = append(optionList, userAgent)
dr := agouti.ChromeDriver(
agouti.ChromeOptions("args", optionList),
agouti.Desired(
agouti.Capabilities{
"loggingPrefs": map[string]string{
"performance": "ALL",
},
"acceptSslCerts": true,
"acceptInsecureCerts": true,
},
),
)
后面的部分跟phantomjs部分的代码一样。
这里也说明一个几个关键的选项和phantomjs使用上的区别。
//无头浏览器模式
–headless
//关闭崩溃日志
–disable-breakpad
//是否加载图片
–blink-settings=imagesEnabled=false
// 忽略ssl错误
–ignore-ssl-errors=true
// 允许非安全内容
–allow-running-insecure-content
//关闭沙箱
–no-sandbox
//关闭zygote进程
–no-zygote
注意两个问题:
page.Destroy()
清理一下。
3. chrome的所有命令行参数可以参考这里:
https://peter.sh/experiments/chromium-command-line-switches/