golang爬虫初体验

简介: 最近在学习golang,看网上很多人都喜欢爬豆瓣,今天我就写了一个golang版的爬虫。对于python爬虫,我很了解,什么dom树,js异步,爬虫技术栈都是没问题的。

最近在学习golang,看网上很多人都喜欢爬豆瓣,今天我就写了一个golang版的爬虫。对于python爬虫,我很了解,什么dom树,js异步,爬虫技术栈都是没问题的。

刚接触golang爬虫,今天写了一个很简单的爬虫,就是使用2个库,一个http、goquery

直接上代码

package main

import (
    "net/http"
    "fmt"
    "github.com/PuerkitoBio/goquery"
    "strconv"
)

func GetMovie(url string) {
    fmt.Println(url)
    resp, err := http.Get(url)
    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("\n")

    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
    resp, err := http.Get(url)
    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 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="
    var urls []string
    var newUrl string
    fmt.Println("%v", urls)
    for i := 0; i < 10; i++ {
        start := i * 25
        newUrl = url + strconv.Itoa(start)
        urls = GetToplist(newUrl)

        for _, url := range urls {
            GetMovie(url)
        }
    }
}

以上是最简单版的,可以优化的地方还有很多,比如使用 协程,请求头,反爬虫机制等。


主要使用的就是 goquery这个库,当然也可以使用正则进行匹配。我是拒绝的。 我很喜欢python中的beautifulsoup。goquery类似jquery,可以直接操作dom树。goquery使用的不熟练,代码写的有很多重复,不优雅。

goquery

Go 实现了类似 jQuery 的功能,包括链式操作语法、操作和查询 HTML 文档。它基于 Go net/html 包和 CSS 选择器库 cascadia。由于 net/html 解析器返回的是 DOM 节点,而不是完整的 DOM 树,因此,jQuery 的状态操作函数没有实现(像 height(),css(),detach())。

由于 net/html 解析器要求文档必须是 UTF-8 编码,因此 goquery 库也有此要求。如果文档不是 UTF-8 编码,使用者需要自己转换。进行编码转换,可以使用如下库:
iconv 的 Go 封装,如:github.com/djimenez/iconv-go
官方提供的 text 子仓库,text/encoding,用于其他编码和 UTF-8 之间进行转换

除了实现和 jQuery 类似的功能外,在函数名方面,也尽量和 jQuery 保持一致,也支持链式语法。

2 goquery 提供的主要类型和方法

2.1 Document

Document 代表一个将要被操作的 HTML 文档,不过,和 jQuery 不同,它装载的是 DOM 文档的一部分。

type Document struct {
    *Selection
    Url      *url.URL
    rootNode *html.Node
}

因为 Document 中内嵌了一个 Selection 类型,因此,Document 可以直接使用 Selection 类型的方法。

有五种方法获取一个 Document 实例,分别是从一个 URL 创建、从一个 *html.Node 创建、从一个 io.Reader 创建、从一个 *http.Response 创建和从一个已有的 Document Clone 一个。

2.2 Selection

Selection 代表符合特定条件的节点集合。

type Selection struct {
    Nodes    []*html.Node
    document *Document
    prevSel  *Selection
}

一般地,得到了 Document 实例后,通过 Dcoument.Find 方法获取一个 Selection 实例,然后像 jQuery 一样使用链式语法和方法操作它。

Selection 类型提供的方法可以分为如下几大类(注意,3个点(…)表示有重载的方法):

1)类似函数的位置操作

– Eq()
– First()
– Get()
– Index…()
– Last()
– Slice()

2)扩大 Selection 集合(增加选择的节点)

– Add…()
– AndSelf()
– Union(), which is an alias for AddSelection()

3)过滤方法,减少节点集合

– End()
– Filter…()
– Has…()
– Intersection(), which is an alias of FilterSelection()
– Not…()

4)循环遍历选择的节点

– Each()
– EachWithBreak()
– Map()

5)修改文档

– After…()
– Append…()
– Before…()
– Clone()
– Empty()
– Prepend…()
– Remove…()
– ReplaceWith…()
– Unwrap()
– Wrap…()
– WrapAll…()
– WrapInner…()

6)检测或获取节点属性值

– Attr(), RemoveAttr(), SetAttr()
– AddClass(), HasClass(), RemoveClass(), ToggleClass()
– Html()
– Length()
– Size(), which is an alias for Length()
– Text()

7)查询或显示一个节点的身份

– Contains()
– Is…()

8)在文档树之间来回跳转(常用的查找节点方法)

– Children…()
– Contents()
– Find…()
– Next…()
– Parent[s]…()
– Prev…()
– Siblings…()

2.3 Matcher 接口

type Matcher interface {
    Match(*html.Node) bool
    MatchAll(*html.Node) []*html.Node
    Filter([]*html.Node) []*html.Node
}

该接口定义了一些方法,用于匹配 HTML 节点和编译过的选择器字符串。Cascadia’s Selector 实现了该接口。

目录
相关文章
|
6月前
|
数据采集 存储 Go
Golang爬虫代理接入的技术与实践
Golang爬虫代理接入的技术与实践
|
3月前
|
数据采集 Go 定位技术
使用go并发网络爬虫
使用go并发网络爬虫
|
11月前
|
数据采集 NoSQL 关系型数据库
Go语言网络爬虫工程经验分享:pholcus库演示抓取头条新闻的实例
网络爬虫是一种自动从互联网上获取数据的程序,它可以用于各种目的,如数据分析、信息检索、竞争情报等。网络爬虫的实现方式有很多,不同的编程语言和框架都有各自的优势和特点。在本文中,我将介绍一种使用Go语言和pholcus库的网络爬虫工程,以抓取头条新闻的数据为例,展示pholcus库的功能和用法。
947 0
Go语言网络爬虫工程经验分享:pholcus库演示抓取头条新闻的实例
|
数据采集 存储 JSON
猜谜游戏、彩云词典爬虫、SOCKS5代理的 Go(Golang) 小实践,附带全代码解释
猜谜游戏在编程语言实践都已经和 HelloWord 程序成为必不可少的新手实践环节,毕竟,它能够让我们基本熟悉 for 循环、变量定义、打印、if else 语句等等的使用,当我们基本熟悉该语言基础之后,就要学会其优势方面的程序实践,比如 Golang 所具备的爬虫及其并发优势。我们将采用彩云词典的英文单词翻译成中文的在线词典爬虫程序,及其改进版本,在并发上,我们将采用 SOCKS5 代理服务器的方式体验 Golang 语言的高并发易用性
92 0
猜谜游戏、彩云词典爬虫、SOCKS5代理的 Go(Golang) 小实践,附带全代码解释
|
程序员 Go 开发工具
【第二章:Golang系列篇】Go基础-环境安装、Go程序初体验
【第二章:Golang系列篇】Go基础-环境安装、Go程序初体验
119 0
|
数据采集 Go
Golang:colly 采用 Go 语言编写的 Web 爬虫框架
Golang:colly 采用 Go 语言编写的 Web 爬虫框架
162 0
Golang:colly 采用 Go 语言编写的 Web 爬虫框架
|
数据采集 数据挖掘 Go
非常好用的爬虫语言Go
如何使用go语言爬取数据
非常好用的爬虫语言Go
|
数据采集 机器人 Python
Python爬虫|反爬初体验
几种简单高效的反爬虫方法总结。
Python爬虫|反爬初体验
|
数据采集 存储 Go
Golang爬虫
示例爬去美女图
334 0
Golang爬虫
|
数据采集 JSON JavaScript
go语言实现网易云音乐爬虫
使用go语言简单实现网易云音乐爬虫
2837 0