chromedp爬取js渲染的数据

lala_dodo · · 3771 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、前提

今天老板要我爬取一个网页table标签中的数据,我用golang中http包发起get请求,返回的body一堆的link标签,href指向js,例如:

<body>
  <noscript>
    <strong>We're sorry but vms doesn't work properly without JavaScript enabled. Please enable it to continue</strong>
  </noscript>
  <div id=app></div>
  <script src=[static/js/chunk-vendors.d270d1df.js](http://www.xxxxxxxx.cn/static/js/chunk-vendors.d270d1df.js)></script>
  <script src=[static/js/app.9c781232.js](http://www.bkhjewelry.cn/static/js/app.9c781232.js)></script>
</body>

即用chrome浏览器右击检查网页源代码的值和检查的值是不一样的。
百度了原因是因为页面中的数据是经过js渲染的。
这个页面如果没有登陆会自动跳转到登陆页面,想说在请求头带上Cookie,但是没有找到这个网页的Cookie(那这是怎么做到的呢,登陆成功之后我也没有在请求头中找到Cookie值,它是怎么判断我是否登陆的呢)
后来百度各种百度,知道了golang的一个库,chromedp,可以模拟浏览器操作。

二、初识Chromedp

三、爬取网页

这里的代码是新版本的Chromedp,网上很多例子都是老版本的,新版本和老版本之间不兼容,我下载的是最新版的Chromedp,百度上很多例子中的方法和库新版本中都没有,最后还是在知乎上找到了一篇可用的文章,感谢那位大佬。

// Command submit is a chromedp example demonstrating how to fill out and
// submit a form.
package main

import (
    "context"
    "fmt"
    "github.com/chromedp/chromedp"
    "log"
    "strings"
    "time"
)

// 定义全局变量,保存网爬取到的网页数据
var htmlContent string

func main() {
    // 设置项,具体参照参考1
    options := []chromedp.ExecAllocatorOption{
        chromedp.Flag("headless", false), // debug使用
        chromedp.Flag("blink-settings", "imagesEnabled=false"),  // 禁用图片加载
        chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`),

    }
    options = append(chromedp.DefaultExecAllocatorOptions[:], options...)

    // Chrome初始化代码如下:
    c, _ := chromedp.NewExecAllocator(context.Background(), options...)

    // create context
    chromeCtx, cancel := chromedp.NewContext(c, chromedp.WithLogf(log.Printf))
    // 执行一个空task, 用提前创建Chrome实例
    chromedp.Run(chromeCtx, make([]chromedp.Action, 0, 1)...)
    // 给每个页面的爬取设置超时时间
    timeoutCtx, cancel := context.WithTimeout(chromeCtx, 30 * time.Second)
    defer cancel()

    //log.Printf("Chrome visit page %s\n", url)

    // run task list
    var res string
    err := chromedp.Run(timeoutCtx, submit(`http://www.xxxxxxxx.cn/#/userAttention`, `//*[@id="app"]/div/div/form/div[1]/div/div[1]/input`, `wu001`, `//*[@id="app"]/div/div/form/div[2]/div/div[1]/input`,`123456`,&res))
    fmt.Println("====res====",res)
    log.Printf("got: `%s`", strings.TrimSpace(res))

    if err != nil {
        log.Fatal("出错了",err)
    }
    fmt.Println("====res====",res)
    log.Printf("got: `%s`", strings.TrimSpace(res))
}


func submit(urlstr, sel, q,sel1,q1  string, res *string) chromedp.Tasks {
    return chromedp.Tasks{
        chromedp.Navigate(urlstr),   // 访问指定url
        chromedp.WaitVisible(sel),  // 等待html中某个元素出现
        chromedp.OuterHTML(`document.querySelector("body")`, &htmlContent, chromedp.ByJSPath),  // 最后获取到<body>标签里的全部HTML代码保存到htmlContent中
        chromedp.SendKeys(sel, q),  // 给选中的元素设置值,这里是填充form表单
        chromedp.SendKeys(sel1, q1),
        chromedp.Click("#app > div > div > form > div.login-btn > button",chromedp.NodeVisible),  // 点击选中的元素
    }
}

暂时只写到这里。后面的数据解析因为密码被修改所以没法登陆
总结一下:
1、代码中可以有多个chromedp.run()
2、获取指定元素的时候,可以通过浏览器的Copy selector和Copy XPath,但是我在填写表单数据的时候,使用selector不能找到指定元素,但是通过XPath可以找到。这个原因未知。
3、官方示例还是很有用的官方示例,示例稍微改动就可以用,前提是得百度一下看一下别人的示例,稍微了解一下chrome的用法,然后可以通过官方示例找到自己想要的功能,参考着写。
4、我还只懂了皮毛。往后该怎么学习这方面的内容呢,还请大家不吝赐教。

四、参考

参考1:https://zhuanlan.zhihu.com/p/139261122

参考2:https://github.com/chromedp/examples


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:lala_dodo

查看原文:chromedp爬取js渲染的数据

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3771 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传