致力于为用户提供真实的
主机测评数据及优惠信息

Golang协程并发爬取图片源码,仅供学习

网友 ***an.net 说:

  1. package main
  2. import (
  3.         &*uot;fmt&*uot;
  4.         &*uot;io/ioutil&*uot;
  5.         &*uot;net/http&*uot;
  6.         &*uot;os&*uot;
  7.         &*uot;regexp&*uot;
  8.         &*uot;strconv&*uot;
  9.         &*uot;st**ngs&*uot;
  10.         &*uot;sync&*uot;
  11.         &*uot;time&*uot;
  12. )
  13. var (
  14.         reImg        = `https?://[^&*uot;]+?(\.((jpg)|(png)|(jpeg)|(gif)|(bmp)))`
  15.         taskChan     chan st**ng                                                      // 记录任务完成的通道
  16.         imgChan      chan st**ng                                                      // 图片通道
  17.         waitG**up    sync.WaitG**up                                                   // 协程会涉及到并发,这个的作用具体的可百度
  18.         pageStart    int            = 1                                               // 从第几页开始
  19.         pageSize     int            = 30                                              // 扫描页数
  20.         DownLoadPath st**ng         = &*uot;D:/HBuilderX/p**ject/GolangP**ject/爬虫小案例/img/&*uot; // 此处是图片下载的地址,需要修改为你们自己的地址
  21. )
  22. func main() {
  23.         fmt.P**ntln(&*uot;从第几页开始&*uot;)
  24.         fmt.Scanln(&pageStart)
  25.         fmt.P**ntln(&*uot;扫描页数&*uot;)
  26.         fmt.Scanln(&pageSize)
  27.         taskChan = make(chan st**ng, pageSize) // 给管道缓冲值
  28.         imgChan = make(chan st**ng, 100000)    // 给管道缓冲值
  29.         for i := pageStart; i < pageStart+pageSize; i++ {
  30.                 waitG**up.Add(1)
  31.                 go getWebBody(i) // 获取地址的body
  32.         }
  33.         waitG**up.Add(1)
  34.         go handleImg() // 处理img
  35.         waitG**up.Add(1)
  36.         go checkOk()
  37.         waitG**up.Wait()
  38.         fmt.P**ntln(&*uot;执行完毕,回车退出&*uot;)
  39.         var input st**ng
  40.         fmt.Scanln(&input)
  41. }
  42. func getWebBody(i int) {
  43.         **l := &*uot;https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/&*uot; + strconv.Itoa(i) + &*uot;.html&*uot;
  44.         resp, err := http.Get(**l)
  45.         if err != nil {
  46.                 fmt.P**ntln(err)
  47.         }
  48.         defer resp.Body.Close() // 此处不可少,否则会造成内存泄露或者溢出问题
  49.         body, _ := ioutil.ReadAll(resp.Body)
  50.         re := regexp.MustCompile(reImg) // 正则匹配图片地址
  51.         result := re.FindAllSt**ngSubmatch(st**ng(body), -1)
  52.         p**ntln(&*uot;第&*uot; + strconv.Itoa(i) + &*uot;页找到数据&*uot; + strconv.Itoa(len(result)) + &*uot;条&*uot;)
  53.         for _, v := range result {
  54.                 imgChan <- v[0] // 把得到的数据写到 管道 里
  55.         }
  56.         taskChan <- **l
  57.         waitG**up.Done()
  58. }
  59. // 处理图片方法
  60. func handleImg() {
  61.         for **l := range imgChan {
  62.                 fileName := GetFilenameF**mUrl(**l)
  63.                 result := DownloadFile(**l, fileName)
  64.                 if result {
  65.                         fmt.P**ntf(&*uot;已下载完毕 %v \n&*uot;, **l)
  66.                 } else {
  67.                         fmt.P**ntf(&*uot;下载失败 %v \n&*uot;, **l)
  68.                 }
  69.         }
  70.         waitG**up.Done()
  71. }
  72. // **管道任务是否完成
  73. func checkOk() {
  74.         count := 0
  75.         for {
  76.                 **l := <-taskChan
  77.                 fmt.P**ntf(&*uot;完成爬取:%v \n&*uot;, **l)
  78.                 count++
  79.                 if count == pageSize {
  80.                         close(imgChan)
  81.                         close(taskChan)
  82.                         break
  83.                 }
  84.         }
  85.         waitG**up.Done()
  86. }
  87. // 截取**l名字
  88. func GetFilenameF**mUrl(**l st**ng) (filename st**ng) {
  89.         // 返回最后一个/的位置
  90.         lastIndex := st**ngs.LastIndex(**l, &*uot;/&*uot;)
  91.         // 切出来
  92.         filename = **l[lastIndex+1:]
  93.         // 时间*解决重名
  94.         timePrefix := strconv.Itoa(int(time.Now().UnixNano()))
  95.         filename = timePrefix + &*uot;_&*uot; + filename
  96.         ret**n
  97. }
  98. // 下载文件方法
  99. func DownloadFile(**l st**ng, filename st**ng) bool {
  100.         var err er**r
  101.         resp, err := http.Get(**l)
  102.         if err != nil {
  103.                 fmt.P**ntln(err)
  104.         }
  105.         defer resp.Body.Close()
  106.         bytes, err := ioutil.ReadAll(resp.Body)
  107.         if err != nil {
  108.                 fmt.P**ntln(err)
  109.         }
  110.         if _, err := os.Stat(DownLoadPath); os.IsNotExist(err) {
  111.                 // 必须分成两步
  112.                 // 先创建文件夹
  113.                 os.Mkdir(DownLoadPath, 0777)
  114.                 // 再修改权限
  115.                 os.Chmod(DownLoadPath, 0666)
  116.         }
  117.         filename = DownLoadPath + filename
  118.         err = ioutil.W**teFile(filename, bytes, 0666)
  119.         if err != nil {
  120.                 ret**n false
  121.         }
  122.         ret**n true
  123. }

网友 Twice 说:

人生苦短,我用PYTHON

网友 Mr.Bean 说:

支持看到了if err 舒服了

赞(0) 打赏
未经允许不得转载:爱主机 » Golang协程并发爬取图片源码,仅供学习
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址