基于golang实现的并发爬虫,爬取图片
代码篇
package mainimport ( "fmt" "io/ioutil" "net/http" "regexp" "strconv" "strings" "sync" "time")// 并发爬思路:// 1.初始化数据管道// 2.爬虫写出:26个协程向管道中添加图片链接// 3.任务统计协程:检查26个任务是否都完成,完成则关闭数据管道// 4.下载协程:从管道里读取链接并下载var ( // 存放图片链接的数据管道 chanImageUrls chan string waitGroup sync.WaitGroup // 用于监控协程 chanTask chan string reImg = `https?://[^"]+?(\.((jpg)|(png)|(jpeg)|(gif)|(bmp)))`)func main() { //DownloadFile("http://i1.shaodiyejin.com/uploads/tu/201909/10242/e5794daf58_4.jpg", "1.jpg") // 1.初始化管道 chanImageUrls = make(chan string,1000000) chanTask = make(chan string, 26) // 2.爬虫协程 for i := 1;i < 3; i++ { waitGroup.Add(1) go getImgUrls("https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/" + strconv.Itoa(i) + ".html") } // 3.任务统计协程,统计26个任务是否都完成,完成则关闭管道 waitGroup.Add(1) go checkOK() // 4.下载协程:从管道中读取链接并下载 for i := 0; i < 3; i++ { waitGroup.Add(1) go DownloadImg() } waitGroup.Wait()}// 下载图片,传入的是图片叫什么func DownloadFile(url string, filename string) (ok bool) { resp, _ := http.Get(url) defer resp.Body.Close() bytes, err := ioutil.ReadAll(resp.Body) filename = "/Users/shiyuxiang/develop/goweb/Crawler/" + filename // 写数据 err = ioutil.WriteFile(filename, bytes, 0666) if err != nil { return false } else { return true }}// 下载图片func DownloadImg() { for url := range chanImageUrls { filename := GetFilenameFromUrl(url) ok := DownloadFile(url,filename) if ok { fmt.Printf("%s 下载成功\n", filename) }else { fmt.Printf("%s 下载失败\n", filename) } } waitGroup.Done()}// 截取url名字func GetFilenameFromUrl(url string) (filename string) { // 返回最后一个/的位置 lastIndex := strings.LastIndex(url, "/") // 切出来 filename = url[lastIndex+1:] // 时间戳解决重名 timePrefix := strconv.Itoa(int(time.Now().UnixNano())) filename = timePrefix + "_" + filename return}// 任务统计协程func checkOK() { var count int for { url := <-chanTask fmt.Printf("%s 完成了爬取任务\n", url) count++ if count == 26 { close(chanImageUrls) break } } waitGroup.Done()}// 爬图片链接到管道// url是传的整页链接func getImgUrls(url string) { fmt.Println(url) urls := getImgs(url) // 遍历切片里所有链接,存入数据管道 for _,url := range urls { chanImageUrls <- url } // 标识当前协程完成 // 每完成一个任务,写一条数据 // 用于监控协程知道已经完成了几个任务 chanTask <- url waitGroup.Done()}// 获取当前页图片链接func getImgs(url string) (urls []string) { pageStr := GetPageStr(url) re := regexp.MustCompile(reImg) results := re.FindAllStringSubmatch(pageStr,-1) fmt.Printf("共找到%d条结果\n", len(results)) for _, result := range results { url := result[0] urls = append(urls, url) } return}// 抽取根据url获取内容func GetPageStr(url string) (pageStr string) { resp,_ := http.Get(url) defer resp.Body.Close() // 2.读取页面内容 pageBytes, _ := ioutil.ReadAll(resp.Body) // 字节转字符串 pageStr = string(pageBytes) return pageStr}
结果:
共找到30条结果https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/2.html 完成了爬取任务共找到30条结果https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/1.html 完成了爬取任务1617623572937548000_eb2323dec01f0815cf654528cb8b1d11.jpg 下载成功1617623572937561000_ecb45559bda357aea824fde70cdde995.jpg 下载成功1617623572937535000_a9f826667ec8ad28d8a20c0d5265c9c6.jpg 下载成功1617623573951542000_8f699a344db3426080a24772a1707813.jpg 下载成功1617623573687566000_4f58f2517f268f71c5937bc432d71902.jpg 下载成功1617623579431880000_1c4669fad1469108c70c438c25e39988.jpg 下载成功
赞 (0)