内容简介:最近在学习golang,看网上很多人都喜欢爬豆瓣,今天我就写了一个golang版的爬虫。对于python爬虫,我很了解,什么dom树,js异步,爬虫技术栈都是没问题的。刚接触golang爬虫,今天写了一个很简单的爬虫,就是使用2个库,一个http、goquery直接上代码
最近在学习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 实现了该接口。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- scrapy 爬虫利器初体验(1)
- Flutter 全栈开发体验——爬虫与服务端
- 爬虫需谨慎,那些你不知道的爬虫与反爬虫套路!
- 反爬虫之字体反爬虫
- 反爬虫之字体反爬虫
- python网络爬虫之初始网络爬虫
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
An Introduction to the Analysis of Algorithms
Robert Sedgewick、Philippe Flajolet / Addison-Wesley Professional / 1995-12-10 / CAD 67.99
This book is a thorough overview of the primary techniques and models used in the mathematical analysis of algorithms. The first half of the book draws upon classical mathematical material from discre......一起来看看 《An Introduction to the Analysis of Algorithms》 这本书的介绍吧!