Go语言使用chromedp爬虫

栏目: Go · 发布时间: 6年前

内容简介:title: Go语言使用chromedp爬虫tags: Go,chromedpauthor: Clown95

title: Go语言使用chromedp爬虫

tags: Go,chromedp

author: Clown95

背景

最近朋友让我帮忙爬取一个网站上面的数据,当时看到页面觉得很简单,虽然有25000多页,但是网站没有反爬虫机制,只要多开几个协程就行。

Go语言使用chromedp爬虫

当我简单的爬取第一页之后,发现url没有page参数。好吧,查看翻页的源代码看看, javascript:__doPostBack('anpDataPager','2') 看到这个翻页我有点头疼,是aps写的后台,通过js调dll内部跳转的。

考虑到一般翻页无非是url和ajax。我又去控制台查看ajax,打开控制台选中 XHR ,结果让我有点懵逼,根本就没有ajax。

Go语言使用chromedp爬虫

我当时就打退堂鼓了,但是又考虑到跟朋友一口一个保证,没办法硬着头皮来吧,那就在url上尝试使用anpDataPager传参看看,还是不行,那就再换curpage依然不行,当我尝试了N遍了常用的curpage参数后,这种方法也以失败告终。

没法比,答应别人的事情当然得尽力完成,就突发奇想使用按键精灵这里脚本语言,模拟手动操作。因为需要查找翻页按钮操作,我只能前台运行。但是有一个很棘手的问题,网站所在服务器速度很慢,大概2-4秒才能显示出数据,而且数据量稍大25675页,我这模拟下去,我得几天不干活。

百度搜索看看有没有其他大佬遇到过类似的情况,你别说还真有,但是大佬使用的 Python 模拟提交form __VIEWSTATE __EVENTTARGET __EVENTARGUMENT __EVENTVALIDATION 这四个数据,我用 go 模仿大佬的方法不知道怎么就是不行。

那就在继续搜索下,看到可以用 seleniumchromedp 来模拟浏览器操作,最终选择了 chromedp

chromedp 介绍

chromedp包是一种更快,更简单的方法,可以使用无外部依赖关系(即Selenium,PhantomJS等)来驱动支持Go中的Chrome DevTools协议的浏览器 。

安装

go get -u github.com/chromedp/chromedp

注意:需要安装chrome浏览器或者chromedrive

使用

官方提供的Demo

https://github.com/chromedp/examples

Api查询地址

https://godoc.org/github.com/chromedp/chromedp

需要爬的内容

<tbody>
                    
                            <tr>
                                <td>1</td>
                                <td>2019/3/22 11:11:31</td>
                                <td>400</td>
                                <td>1,000,000</td>
                                <td>1,000</td>
                                <td>1,000,400</td>
                                <td>aabb123</td>
                                <td> </td>
                                <td>92fox</td>
                                <td>92fox</td>
                                <td>上分</td>
                            </tr>
                        
                        .....
                        
                </tbody>

我直接贴上我爬虫的代码

package main

import (
    "context"
    "errors"
    "github.com/chromedp/cdproto/cdp"
    "github.com/chromedp/cdproto/network"
    "time"
    "log"
    "github.com/chromedp/chromedp"
)

var res string  // 定义全局变量,用来保存爬虫的数据

func main() {
    var err error
        
    // 创建链接
    ctxt, cancel := context.WithCancel(context.Background())
    defer cancel()
 
    //创建chrome.New()创建新的chrome实例
    c, err := chromedp.New(ctxt, chromedp.WithLog(log.Printf)) 
    if err != nil {
        log.Fatal(err)
    }
    x, err := chromedp.New(ctxt, chromedp.WithLog(log.Printf))
    if err != nil {
        log.Fatal(err)
    }
    //执行任务
    err = c.Run(ctxt, visitWeb("http://dl.gaggjz.pw:8086/OpRoot/MemberScoreList.aspx?uid=0&op=0&uname=sdafsadsaf"))
    if err != nil {
        log.Fatal(err)
    }
    // 循环翻页
    for i := 1; i < 25000; i++ {
        //执行
        err = x.Run(ctxt, DoCrawler()) //执行爬虫任务
        WirteTXT(res)// res的内容写入文本 
    }

}

// 任务 主要用来设置cookie ,获取登录账号后的页面
func visitWeb(url string) chromedp.Tasks {

    return chromedp.Tasks{  
        chromedp.ActionFunc(func(ctxt context.Context, h cdp.Executor) error {
            expr := cdp.TimeSinceEpoch(time.Now().Add(180 * 24 * time.Hour))
            success, err := network.SetCookie("ASP.NET_SessionId", "这里是值"). //设置cookie
                WithExpires(&expr).
                WithDomain("dl.gaggjz.pw:8086"). //访问网站主体
                WithHTTPOnly(true).
                Do(ctxt, h)
            if err != nil {
                return err
            }
            if !success {
                return errors.New("could not set cookie")
            }

            return nil
        }),
        chromedp.Navigate(url), //页面跳转
    }
}
// 任务 主要执行翻页功能和或者html
func DoCrawler() chromedp.Tasks {

    //sel =fmt.Sprintf(`javascript:__doPostBack('anpDataPager','%s')`,"2")

    return chromedp.Tasks{
        chromedp.Sleep(1*time.Second), // 等待
        chromedp.WaitVisible(`#form1`, chromedp.ByQuery),等待id=from1页面可见  ByQuery是使用DOM选择器查找
        chromedp.Sleep(1*time.Second), 
        chromedp.Click(`.pagination li:nth-last-child(4) a`, chromedp.ByQuery),//点击翻页
        chromedp.OuterHTML(`tbody`, &res, chromedp.ByQuery), //获取改 tbody标签的html
    }
}


func WirteTXT(txt  string ) {
    f, err := os.OpenFile("1.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
    if err != nil {
        fmt.Println("os Create error: ", err)
        return
    }
    defer f.Close()

    bw := bufio.NewWriter(f)
    bw.WriteString(txt+"\n")
    bw.Flush()
}

总结

通过代码可以看到我创建了 chromedp.Tasks 任务,第一个任务主要就是为了设置cookie即模拟登录,第二个任务是最重要的,它主要用来点击下一页按钮和获取指定html内容。因为第一次接触chromedp,所以我刚开始把两个任务放在一个任务里,就造成了第一页和第二页来回跳转。所以突发奇想创建了2个任务。当然我后来才知道,单独执行第二个任务的时候,可以手动输入地址和登录账号,程序也是可以执行的,就是有个缺点,执行一段时间可能cookie失效,需要重新登录。要注意的是chromedp使用的是DOM 原生选择器,我刚开始看到ByQuery 以为可以使用JQuery选择器,一直筛选不到内容。 还有一个坑点就是,我爬取的td标签是在tbody内的,直接使用 chromedp.Text() 获取不到内容,所以退而求次,获取了html,但是我发现goquery 读取文本里面的html也不能获取到td的内容,最后我把tbody替换成table,可以成功的获取到内容。


以上所述就是小编给大家介绍的《Go语言使用chromedp爬虫》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Web Designer's Idea Book, Vol. 2

The Web Designer's Idea Book, Vol. 2

Patrick McNeil / How / 2010-9-19 / USD 30.00

Web Design Inspiration at a Glance Volume 2 of The Web Designer's Idea Book includes more than 650 new websites arranged thematically, so you can easily find inspiration for your work. Auth......一起来看看 《The Web Designer's Idea Book, Vol. 2》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具