记得去年开始学习用 Python 写爬虫,第一次写了个爬取豆瓣电影 Top 250,最近在学习 Go 语言,也尝试用 Go 重新写爬虫。写完之后感觉很爽,仅仅不到 100 行的代码,就实现了获取 HTML,解析,模型定义,数据库持久化等功能。而且运行速度比 Python 简直是一个天上一个地下。

爬虫框架使用的是 colly,封装的已经非常简洁了,仅仅只需要在相关的回调函数里编写相关的逻辑,就能快速完成一个简单的爬虫。在 OnResponse 回调中可以使用 goquery 来解析需要的内容。用法和 Python 里的 BeautifulSoup 类似。

c := colly.NewCollector(
		colly.AllowedDomains("movie.douban.com"),
	)

	c.OnHTML("span[class=next]", func(e *colly.HTMLElement) {
		link, _ := e.DOM.Find("link").Attr("href")
		e.Request.Visit(link)
	})
	
	c.OnResponse(func(s *colly.Response) {
		dom, err := goquery.NewDocumentFromReader(strings.NewReader(string(s.Body)))
		if err != nil {
			fmt.Println(err)
		}

		dom.Find("div[class=item]").Each(func(i int, s *goquery.Selection) {
			title := s.Find("span[class=title]").Text()
			fmt.Println(title)

			rank := s.Find("span[class=rating_num]").Text()
			fmt.Println(rank)

			poster, _ := s.Find("img").Attr("src")
			fmt.Println(poster)

			content := s.Find("p").Text()
			fmt.Println(content)

			detail := s.Find("span[class=inq]").Text()
			fmt.Println(detail)

			movie := &Movie{
				Name:   title,
				Rank:   rank,
				Poster: poster,
				Detail: detail,
			}
			db.Create(movie)
		})
	})

	c.OnRequest(func(r *colly.Request) {
		fmt.Println("Visting", r.URL)
	})

	c.OnError(func(e *colly.Response, err error) {
		fmt.Println("error", err)
	})

	c.Visit("https://movie.douban.com/top250")

这次我用 Docker 启动了一个 PostgreSQL,以后想抛弃 MySQL 了,数据库持久化使用的是 gorm 这个 ORM 库,加个 db 驱动就能正常连接了。模型定义也很简洁:

type Movie struct {
	gorm.Model
	Name   string `json:"name";gorm:"not_null"`
	Rank   string `json:"rank";gorm:"not_null"`
	Poster string `json:"poster";gorm:"not_null"`
	Detail string `json:"detail";gorm:"not_null"`
}

需要注意的地方

  • 连接数据库成功之后,先加一句:defer db.Close(),以便在使用结束之后自动关闭数据库连接。
  • 数据库驱动的 import 可以这样写:_ "github.com/lib/pq",因为并未在程序中显式使用。
  • gorm 已经为我们的 Model 自动添加 ID 作为主键了,模型定义这里,不需要再加 ID,否则会报错。