• Golang 爬虫系列一 goquery


    主要参考原文在https://www.jianshu.com/p/ae172d60c431

    主要想练习一下goquery,首先是实践一把  使用goquery爬取豆瓣电影top250

    从原文最后复制代码,编译运行。输入一堆err

    调试了一下,返回Http错误代码418,应该是反爬虫了。

    好吧,我们不应增加服务器的负担,但也不应该逼着我们每次用自己的眼球看吧,用程序读网页又怎么啦!

    于是,把程序中的循环去掉,只读取第一页,并增加请求头试试。

    package main
    
    import (
        "fmt"
        "net/http"
    
        "github.com/PuerkitoBio/goquery"
    )
    
    func GetMovie(url string) {
        fmt.Println(url)
        //new 一个 request,再设置其header
        req, _ := http.NewRequest("GET", url, nil)
        // 设置
        req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML,like GeCKO) Chrome/45.0.2454.85 Safari/537.36 115Broswer/6.0.3")
        req.Header.Set("Referer", "https://movie.douban.com/")
        req.Header.Set("Connection", "keep-alive")
        resp, err := (&http.Client{}).Do(req)
        if err != nil {
            panic(err)
        }
        //bodyString, err := ioutil.ReadAll(resp.Body)
        //fmt.Println(string(bodyString))
        if resp.StatusCode != 200 {
            fmt.Println("err")
        }
    
        doc, err := goquery.NewDocumentFromReader(resp.Body)
        if err != nil {
            panic(err)
        }
    
        //
    
        doc.Find("#content h1").Each(func(i int, s *goquery.Selection) {
            // name
            fmt.Println("name:" + s.ChildrenFiltered(`[property="v:itemreviewed"]`).Text())
            // year
            fmt.Println("year:" + s.ChildrenFiltered(`.year`).Text())
        })
    
        // #info > span:nth-child(1) > span.attrs
        director := ""
        doc.Find("#info span:nth-child(1) span.attrs").Each(func(i int, s *goquery.Selection) {
            // 导演
            director += s.Text()
            //fmt.Println(s.Text())
        })
        fmt.Println("导演:" + director)
        //fmt.Println("
    ")
    
        pl := ""
        doc.Find("#info span:nth-child(3) span.attrs").Each(func(i int, s *goquery.Selection) {
            pl += s.Text()
        })
        fmt.Println("编剧:" + pl)
    
        charactor := ""
        doc.Find("#info span.actor span.attrs").Each(func(i int, s *goquery.Selection) {
            charactor += s.Text()
        })
        fmt.Println("主演:" + charactor)
    
        typeStr := ""
        doc.Find("#info > span:nth-child(8)").Each(func(i int, s *goquery.Selection) {
            typeStr += s.Text()
        })
        fmt.Println("类型:" + typeStr)
    }
    
    func GetToplist(url string) []string {
        var urls []string
        //new 一个 request,再设置其header
        req, _ := http.NewRequest("GET", url, nil)
        // 设置
        req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML,like GeCKO) Chrome/45.0.2454.85 Safari/537.36 115Broswer/6.0.3")
        req.Header.Set("Referer", "https://movie.douban.com/")
        req.Header.Set("Connection", "keep-alive")
        resp, err := (&http.Client{}).Do(req)
        if err != nil {
            panic(err)
        }
        fmt.Println("===============================================================", resp.StatusCode)
        //bodyString, err := ioutil.ReadAll(resp.Body)
        //fmt.Println(string(bodyString))
        if resp.StatusCode != 200 {
            fmt.Println("//////////////////////////////////////", resp.StatusCode)
        }
    
        doc, err := goquery.NewDocumentFromReader(resp.Body)
        if err != nil {
            panic(err)
        }
    
        doc.Find("#content div div.article ol li div div.info div.hd a").
            Each(func(i int, s *goquery.Selection) {
                // year
                fmt.Printf("%v", s)
                herf, _ := s.Attr("href")
                urls = append(urls, herf)
            })
        return urls
    }
    
    func main() {
        url := "https://movie.douban.com/top250?start=0"
        var urls []string
        urls = GetToplist(url)
        fmt.Println("%v", urls)
        for _, url := range urls {
            GetMovie(url)
        }
    
    }

    感谢开放的豆瓣,憎恶搞封闭的互联网霸权!成功读取到了所需要的信息!

    下面正式进入goquery正题,这部分主要参考https://www.flysnow.org/2018/01/20/golang-goquery-examples-selector.html

    1、基于HTML Element 元素的选择器

    这个比较简单,就是基于a,p等这些HTML的基本元素进行选择,这种直接使用Element名称作为选择器即可。比如dom.Find("div")

    func main() {
        html := `<body>
    
                    <div>DIV1</div>
                    <div>DIV2</div>
                    <span>SPAN</span>
    
                </body>
                `
    
        dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
        if err!=nil{
            log.Fatalln(err)
        }
    
        dom.Find("div").Each(func(i int, selection *goquery.Selection) {
            fmt.Println(selection.Text())
        })
    }

     以上示例,可以把div元素筛选出来,而body,span并不会被筛选。

     2、ID 选择器

    这个是使用频次最多的,类似于上面的例子,有两个div元素,其实我们只需要其中的一个,那么我们只需要给这个标记一个唯一的id即可,这样我们就可以使用id选择器,精确定位了。

    func main() {
        html := `<body>
    
                    <div id="div1">DIV1</div>
                    <div>DIV2</div>
                    <span>SPAN</span>
    
                </body>
                `
    
        dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
        if err!=nil{
            log.Fatalln(err)
        }
    
        dom.Find("#div1").Each(func(i int, selection *goquery.Selection) {
            fmt.Println(selection.Text())
        })
    }

    id选择器以#开头,紧跟着元素id的值,使用语法为dom.Find(#id),后面的例子我会简写为Find(#id),大家知道这是代表goquery选择器的即可。

    3、Element ID 选择器

    如果有相同的ID,但是它们又分别属于不同的HTML元素怎么办?有好办法,和Element结合起来。比如我们筛选元素为div,并且iddiv1的元素,就可以使用Find(div#div1)这样的筛选器进行筛选。

    所以这类筛选器的语法为Find(element#id),这是常用的组合方法,比如后面讲的过滤器也可以采用这种方式组合使用。

    其他选择器不想写了,大家可参考原文。但我想应该可以直接从chromer开发工具中copy 相应的selector

    其他参考:

    https://www.cnblogs.com/winterbear/p/12263886.html

    https://www.cnblogs.com/mingbai/p/goHttpReq.html

  • 相关阅读:
    JDOM入门实例:读取与创建xml文档
    C++构造函数/析构函数/拷贝构造函数/深拷贝浅拷贝解析
    java类的访问权限
    hive怎样决定reducer个数
    hive Cli常用操作(翻译自Hive wiki)
    hive local hadoop特性
    hive数据操作(翻译自Hive wiki+实例讲解)
    hive的hive.exec.parallel参数说明
    hive数据类型(翻译自Hive Wiki)
    hive 创建/删除/截断 表(翻译自Hive wiki)
  • 原文地址:https://www.cnblogs.com/pu369/p/12964951.html
Copyright © 2020-2023  润新知