Golang页面爬虫下载图片之初体验

1,184 阅读1分钟

说明

本文示例爬取的是懒人图库>首页>免抠PNG>卡通手绘一栏的列表图片,打开列表页面和下载图片均使用协程处理,图片保存目录在./data/img/(没有时会自动新建)。

代码

安装依赖

#仅需要安装一个,jQeury的go实现,用来获取html节点信息
go get github.com/PuerkitoBio/goquery

爬虫代码

package main

import (
	"bytes"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

type imgInfo struct {
	url  string
	name string
}

var pageChan = make(chan string, 1000)
var htmlChan = make(chan string, 1000)
var imgChan = make(chan imgInfo, 1000)
var isFinish = make(chan bool)

//抓取某站特定页面的图片
func main() {
	//目标地址,页码拼在最后
	baseUrl := "https://www.lanrentuku.com/pngsucai/cate_katongshouhui_"
	//就爬几页试试水
	for i := 1; i <= 2; i++ {
		pageChan <- baseUrl + strconv.Itoa(i)
	}

	//协程获取网页内容,放入通道
	go getPage()
	//协程获取网页内容中的图片链接,放入通道
	go parsePage()
	//协程根据通道中的图片链接,下载图片到本地
	go downloadImg()

	<-isFinish
	fmt.Println("全部处理完成!")
}

// checkErr 处理可能的错误信息
func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

func getPage() {
	for page := range pageChan {
		fmt.Println("当前正在抓取页面:" + page)
		r, _ := http.Get(page)
		body, _ := ioutil.ReadAll(r.Body)
		htmlChan <- string(body)

		r.Body.Close()
		time.Sleep(time.Millisecond * 300)
	}
}

func parsePage() {
	for html := range htmlChan {
		dom, err := goquery.NewDocumentFromReader(strings.NewReader(html))
		checkErr(err)
		//遍历页面的目标图片节点,获取图片url和文件名
		dom.Find(".list-pic .item-img img").Each(func(i int, selection *goquery.Selection) {
			imgUrl, ok := selection.Attr("src")
			if ok {
				imgName, ok := selection.Attr("alt")
				if !ok {
					imgName = path.Base(imgUrl)
				} else {
					imgName += path.Ext(imgUrl)
				}

				imgChan <- imgInfo{name: imgName, url: imgUrl}
			}
		})
	}
}

func downloadImg() {
	for {
		select {
		case img := <-imgChan:
			//图片url: "https://d1.lanrentuku.com/upload/cover/5fac9b67d30bd.jpg"
			//创建目录
			err := os.MkdirAll("./data/img", os.ModePerm)
			checkErr(err)

			//保存图片
			fmt.Println("正在保存的图片:", img.url)
			f, err := os.Create("./data/img/" + img.name)
			checkErr(err)
			r, _ := http.Get(img.url)
			body, _ := ioutil.ReadAll(r.Body)
			io.Copy(f, bytes.NewReader(body))

			//释放资源
			r.Body.Close()
			f.Close()
			//取之有度
			time.Sleep(time.Millisecond * 300)

		case <-time.After(time.Second * 15):
			//超时终止程序
			isFinish <- true
		}
	}
}

页面信息示例

下载好的图片

参考