发现之前写的 shein 爬虫突然失效了。页面返回提示: Enable JavaScript and cookies to continue
- us.shein.com needs to review the security of your connection before proceeding.
- Ray ID: 78698c2b8b837cdd
- Performance & security by Cloudflare
-
尝试更换代理IP, 请求头,都没用。根据提示来看,确实被反爬了。应该启用 JS渲染。
考虑到Go语言常用的 chromedp 浏览器爬虫,效率较低。想起以前使用python的 scrapy 爬虫框架时,结合 Splash 可做 JS渲染 服务,挺好用的。想着 Splash 本身基于HTTP的API, 是跨语言的,应该可以代替 chromedp 来做浏览器渲染。
使用 Docker (version >= 17), 安装 Splash 服务.
- # 下载 splash 镜像
- sudo docker pull scrapinghub/splash
- # 启动 splash 容器。因需要使用宿主机的HTTP代理服务。故添加 --net host 参数
- sudo docker run -it --net host -p 8050:8050 --rm scrapinghub/splash
-
docker run 命令添加参数 --net host, 使容器能使用宿主机网络环境的HTTP代理服务。
如此,便开启了一个运行Splash应用的Docker容器,该容器共享宿主机网络。
访问地址: http://127.0.0.1:8050
发起一个 GET方法 的HTTP请求,使用 splash 的 JS渲染 服务。流程如下:
使用 Splash 的API接口 的 execute (或 run)方法,在 lua_source 参数中携带执行脚本参数。
lua_source 参数示例:
- function main(splash)
- return 'hello'
- end
-
通过curl命令调用API接口示例:
- # execute 方法
- curl 'http://127.0.0.1:8050/execute?lua_source=function+main%28splash%29%0D%0A++return+%27hello%27%0D%0Aend'
-
Golang语言中,请使用 net/url 包的 url.QueryEscape 方法对 lua_source 参数进行 urlEncode 转义。
伪代码如下所示:
- import (
- "fmt"
- neturl "net/url"
- "strconv"
- "strings"
- "time"
- "github.com/gocolly/colly/v2"
- )
-
- func GetSplashUrl(url string) string {
- luaSourceFmt := `splash:on_request(function(request)
- request:set_proxy{"0.0.0.0",1079}
- end)
- splash:set_user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
- assert(splash:go("%s"))
- return splash:html()
- `
- q := neturl.QueryEscape(fmt.Sprintf(luaSourceFmt, url))
- return "http://127.0.0.1:8050/run?lua_source=" + q
- }
-
- func main(){
- reqUrl := GetSplash("https://www.example.com")
- // TODO 通过reqUrl发起HTTP请求,返回结果已被Splash处理过,为JS渲染过的HTML页面。
- }
-
execute 方法接口的 lua_source 参数如下所示:
- function main(splash, args)
- assert(splash:go(args.url))
- assert(splash:wait(1.0))
- return splash:html()
- end
-
run 方法接口的 lua_source 参数如下所示:
- assert(splash:go(args.url))
- assert(splash:wait(1.0))
- return splash:html()
-
request 对象 在 splash:on_request(callback) 方法的回调函数中调用
splash:on_request(callback) 设置一个回调函数,用于在发起HTTP请求前,操作 request 对象
- # 添加代理
- splash:on_request(function(request)
- request:set_proxy{
- host = "0.0.0.0",
- port = 8990,
- username = splash.args.username,
- password = splash.args.password,
- }
- end)
-
https://splash.readthedocs.io/en/stable/scripting-tutorial.html
https://splash.readthedocs.io/en/stable/scripting-ref.html#splash-on-request
request 请求对象 https://splash.readthedocs.io/en/stable/scripting-request-object.html