最近学完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()
}
程序员,产品 9.1 PHP Go 前端 JwCode 渐悟分享