go 并发爬虫爬取美女图片

最近学完go了想实战一下,于是就试试并发爬取数据吧


找了一个网站 优图 

内容涉及到了

正则

时间

匿名函数线程的

下边是代码

package main

import (
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)

/*
//爬取图片
//http://www.uutu.me/index.php?c=Article&id=6671

<div align="center">
<a href="http://www.uutu.me/index.php?c=Article&id=6671&p=3">
<img class="img-responsive" alt="[IMiss]爱蜜社 2018.11.30 Vol.310 王雨纯" src="http://d.kancaijing.com.cn/attach/2020-01-17/1579252699Pphy.jpg" title="点击查看下一张" border="0"><br>
<p>[IMiss]爱蜜社 Vol.310 王雨纯</p>
<p>(点击图片查看下一页) </p>
</a>

</div>
*/
var (
	ch = make(chan []string,10)
	chns = make(chan int,100)
	downAsyncWG1 sync.WaitGroup
	downAsyncWG2 sync.WaitGroup
	RMT          sync.Mutex
	Url     = "http://www.uutu.me/index.php?c=Article&id=6671"
			    //`<img[\s\S]+?data-original="(http[\s\S]+?)"`
	re       = `align="center"[\s\S]+?href="(http[\s\S]+?)">[\s\S]+?class="img-responsive"[\s\S]+?alt="([\s\S]+?)"[\s\S]+?src="(http[\s\S]+?\.(jpg|png))"` //`1[345678]\d{9}`
)

//获取随机数
func getRandNum() int {
	RMT.Lock()
	<-time.After(1 * time.Nanosecond)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	ret := int(time.Now().UnixNano()) - r.Intn(int(int(time.Now().Unix())))
	RMT.Unlock()
	return ret
}

//文件名
func getFileName(strimg string) string {

	strimg = strings.Replace(strimg, " ", "_", -1)
	str := strconv.Itoa(int(time.Now().UnixNano()))
	str2 := `E:\Go\src\Tools\分布式爬虫\img_103\` + strimg + "_" + str + "_" + strconv.Itoa(getRandNum()) + ".jpg"
	return str2
}

func handErrs(err error, wen string) {
	if err != nil {
		fmt.Println(wen, err.Error())
		os.Exit(1)
	}
}

func getUrlHtml(str string) string {
	resp, err := http.Get(str)
	defer resp.Body.Close()
	handErrs(err, "url")
	bytes, _ := ioutil.ReadAll(resp.Body)
	//handErrs(err, "解析返回错内容")
	return string(bytes)
}

// 传入url 和 正则规则 返回地址列表
func getImageUrl(url,reStr string) (images []string) {
	html := getUrlHtml(url)
	str := regexp.MustCompile(reStr)
	wangyi := str.FindAllStringSubmatch(html,-1)
	//fmt.Println(wangyi)

	//images = make([]string,0)
	for _,link := range wangyi{
		images = append(images,link[1],link[2],link[3]) //下一张链接 名字 图片地址
	}
	return
}


//下载 参数 url
func downloads(str []string) {
	fmt.Println("开始下载"+ str[1] +"........")
	resp, err := http.Get(str[2])
	defer resp.Body.Close()
	handErrs(err, "downloads-url")
	imgbytes, err := ioutil.ReadAll(resp.Body)
	if err != nil{
		fmt.Println("报错了:", err.Error())
		time.Sleep(time.Hour)
		return
	}
	handErrs(err, "解析返回错内容")
	filename := getFileName(str[1])
	err = ioutil.WriteFile(filename, imgbytes, 0777)
	handErrs(err, "ioutil.WriteFile")
	fmt.Println(str[1] + "下载完成........")
}

func downAsync(str []string) {
	downAsyncWG2.Add(1)
	go func(str []string) {
		downloads(str)
		downAsyncWG2.Done()
	}(str)

}

func down(Url string)  {

	downAsyncWG1.Add(1)
	go func() {
		aaaa(Url)
		downAsyncWG1.Done()
	}()
	downAsyncWG1.Wait()
}

func aaaa(Url string)   {
	arr := getImageUrl(Url,re)
	fmt.Println(arr[0],arr[1],arr[2])
	ch <- arr
	down(arr[0])

}

func main() {
	go func() {
		for  {
			select {
			case aa := <-ch :
				fmt.Println(aa)
				downAsync(aa)
			}
		}
	}()
	down(Url)
	downAsyncWG2.Wait()
}
伍先生
  • 职业: 程序员,产品
  • 码龄: 8.7
  • 技能: PHP Go 前端
  • 微信: JwCode
  • 公众号/小程序: 渐悟分享