golang 多线程爬虫

时间:2025-03-30 13:31:22
这是一个golang爬虫demo 爬去一个美女图片网站的首页所有图片
采用golang 多线程的方式爬取图片 将爬到的图片保存到本地
代码中有用到goquery 网页数据解析框架 chan 控制goroutine 进行下载

/
一个妹子图片网站  请求的 header 必须带着 Referer 否则404 (比较简单的一种反爬虫策略)
用wireshark 抓取浏览器请求图片的数据就可以得到 Referer

//代码不复杂,适合新手学习
var url = "/"

var c chan int

func main() {
	(4)
	spider()
	//testDownLoad()
}

//url->Document->所有图片url->开启多线程进行下载->保存到本地
func spider() {
	doc, err := (url)
	if err != nil {
		(err)
	}
	urls := ImageRule(doc, match);
	("共解析到", len(urls), "图片地址")
	c = make(chan int)
	for _, s := range urls {
		(s)
		go downloadImage(s)
	}
	//可以等待一会儿,留时间给子goroutine 执行
	//但是这种方式不怎么靠谱 //直接采用chan 的方式
	//(1e9*10)
	for i := 0; i < len(urls); i++ {
		<-c
	}
}

// 单独测试了以下 下载方法
func testDownLoad() {
	var url_img = "/uploads/tu/201608/164/";
	//var  url_img  = "/uploads/tu/sm/201601/19/";
	downloadImage(url_img)
}

func match(image string) {
	(image);
}

func getData(url string) (eader , err error) {
	req := buildRequest(url)
	resp, err := (req)
	defer ()
	return (), err
}

// 得到一个网页中所有 ImageUrl
func parseImageUrl(reader ) (res []string, err error) {

	doc, err := (reader)
	if err != nil {
		return nil, err
	}
	()
	ImageRule(doc, func(image string) {
		res = append(res, image)
	})
	return res, nil
}

func ImageRule(doc *, f func(image string)) (urls []string) {
	str := make([]string, 0)
	//直接找以img 开头的标签 过滤掉不符合规则的url 即可
	("img").Each(func(i int, s *) {
		url, result := ("src")
		if result {
			if (url, ".jpg") {
				str = append(str, url)
			}
		}
	})
	return str
}

//根据url 创建http 请求的 request
//网站有反爬虫策略 wireshark 不解释
func buildRequest(url string) * {
	req, err := ("GET", url, nil)
	if err != nil {
		panic(err)
	}
	//	("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36")
	//	("Cookie", "Hm_lvt_c605a31292b623d214d012ec2a737685=1516111586; Hm_lpvt_c605a31292b623d214d012ec2a737685=1516111613")
	//("If-None-Match", "5a309bab-26057")
	("Referer", "/")
	//("If-Modified-Since", "Wed, 13 Dec 2017 03:16:59 GMT")
	return req
}
// 下载图片
func downloadImage(url string) {
	fileName := getNameFromUrl(url)
	req := buildRequest(url)
	 = 10 * ;
	resp, err := (req)
	if err != nil {
		("failed download ")
		panic(err)
	}
	if  !=  {
		("failed download " + url)
		return
	}
	defer func() {
		()
		if r := recover(); r != nil {
			(r)
		}
		c <- 0
	}()

	("begin download " + fileName)
	("./images/", 0777)
	localFile, _ := ("./images/"+fileName, os.O_CREATE|os.O_RDWR, 0777)

	if _, err := (localFile, ); err != nil {
		panic("failed save " + fileName)
	}

	("success download " + fileName)
}
// 判读文件夹是否存在
func isExist(dir string) bool {
	_, err := (dir)
	if err == nil {
		return true
	}
	return (err)
}

// 通过url 得到图片名字
func getNameFromUrl(url string) string {
	arr := (url, "/")
	return arr[len(arr)-1]
}
项目地址:点击打开链接
goquery 传送门 //PuerkitoBio/goquery