我的Go+语言初体验——用go+写一个图片下载神器,百来行代码的事儿

BigDataToAI 社区中级贡献者 2021-12-08 02:19:16

目录

前言

该工具最初的构想

定义返回参数数据结构

通过动态请求获取图片下载地址

保存路径

构建http服务

完整代码

一步一步看成果

打成exe文件

下载体验


前言

最近遭遇了图片荒(每次写文章都要附上一些图片心里才踏实)。之前去shopify上一张一张下载了一些图片,但是很快就用完了。刚好最近和go+社区小伙伴一起学习go+,就想着用go+写个批量下载图片的工具,晚上回来找了一下资料没想到百来行代码就写好了。

最后成果:

 

工具说明:该工具用于从https://pixabay.com/zh/网站免费下载无版权高清图片(通过网站注册获取api key,通过填写想要下载的图片特征、图片类型即可将图片保存到指定的路径)。

该工具最初的构想

刚好早上在网上找哪里有免费无版权的图片时找到https://pixabay.com/zh/可以提供大量高清无版权图片,并有api尽心调用下载。

构想:用go+构建一个web应用,通过web图形化界面配置将图片下载到本地。

最终:用go+与html实现

先说一下https://pixabay.com/zh/这个网站提供的免费图片的调用方式,使用get调用如下请求,请求参数包括:key(网站注册之后获取的api key),q(需要下载的图片特征),image_type(图片类型)。而返回参数也如下所示。更具体的可注册上述网站之后访问https://pixabay.com/api/docs/查看。

 

定义返回参数数据结构

所以说,首先第一步我要做的就是用在go+中定义一个数据结构,用来表示返回参数:

如下所示:

type Hit struct {
  ID              int    `json:"id"`
  PageURL         string `json:"pageURL"`
  Type            string `json:"type"`
  Tags            string `json:"tags"`
  PreviewURL      string `json:"previewURL"`
  PreviewWidth    int    `json:"previewWidth"`
  PreviewHeight   int    `json:"previewHeight"`
  WebformatURL    string `json:"webformatURL"`
  WebformatWidth  int    `json:"webformatWidth"`
  WebformatHeight int    `json:"webformatHeight"`
  LargeImageURL   string `json:"largeImageURL"`
  FullHDURL       string `json:"fullHDURL"`
  ImageURL        string `json:"imageURL"`
  ImageWidth      int    `json:"imageWidth"`
  ImageHeight     int    `json:"imageHeight"`
  ImageSize       int    `json:"imageSize"`
  Views           int    `json:"views"`
  Downloads       int    `json:"downloads"`
  Likes           int    `json:"likes"`
  Comments        int    `json:"comments"`
  UserID          int    `json:"user_id"`
  User            string `json:"user"`
  UserImageURL    string `json:"userImageURL"`
}

type Result struct {
  Total     int   `json:"total"`
  TotalHits int   `json:"totalHits"`
  Hits      []Hit `json:"hits"`
}

通过动态请求获取图片下载地址

接着就可以调用上述接口对图片进行下载啦,但是请注意,我们要做的是图形化界面配置要,所以上述说到的请求参数当然不可以在代码中写死,而是通过downloadImages.gtpl前端界面表单请求的方式来获取

func DownloadImages(w http.ResponseWriter, r *http.Request) {

  if r.Method == "GET" {
    t, _ := template.ParseFiles("downloadImages.gtpl")
    log.Println(t.Execute(w, nil))
  } else {
    err := r.ParseForm()
    if err != nil {
      log.Fatal("ParseForm: ", err)
    }

    println("key:", r.Form["key"])
    println("q:", r.Form["q"])
    println("image_type:", r.Form["image_type"])
    println("save_path:", r.Form["save_path"])

    _, keyOk := r.Form["key"]
    _, qOk := r.Form["q"]
    _, imageTypeOk := r.Form["image_type"]
    _, savePathOk := r.Form["save_path"]
    if !keyOk || !qOk || !imageTypeOk || !savePathOk {
      fmt.Fprintf(w, "请输入正确的参数")
      return
    }

    resp, err := http.Get("https://pixabay.com/api/?key=" + r.Form["key"][0] + "&q=" + r.Form["q"][0] + "&image_type=" + r.Form["image_type"][0])

    if err != nil {
      panic(err)
    }

    var res Result

    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    json.Unmarshal(body, &res)
    for i, hit := range res.Hits {
      println(i, hit.LargeImageURL)

      var iURLSplit = strings.Split(hit.LargeImageURL, "/")

      imageResp, err := http.Get(hit.LargeImageURL)

      defer resp.Body.Close()

      CreatePathIfNotExists(r.Form["save_path"][0])

      if err != nil {
        panic(err)
      }

      out, err := os.Create(r.Form["save_path"][0] + iURLSplit[len(iURLSplit)-1])
      if err != nil {
        panic(err)
      }
      defer out.Close()
      _, err = io.Copy(out, imageResp.Body)
      if err != nil {
        panic(err)
      }
    }
    fmt.Fprintf(w, "图片下载完成,下载路径为:"+r.Form["save_path"][0])
  }
}

保存路径

当然还有一点,我们可以动态配置我们想要下载的图片,那当然也要能够动态配置保存的路径啦,所以我们还开放了参数,用于图片保存的路径。

下述代码表示如果配置的路径不存在,则新建文件夹

func CreatePathIfNotExists(path string) {
  _, err := os.Stat(path)
  if os.IsNotExist(err) {
    os.Mkdir(path, os.ModePerm)
  }
}

构建http服务

基于上述逻辑,我们就可以启用一个http服务

http.HandleFunc("/", DownloadImages)     // 设置访问的路由
err := http.ListenAndServe(":8888", nil) // 设置监听的端口

if err != nil {
  log.Fatal("ListenAndServe: ", err)
}

完整代码

最后附上完整的gop代码和html代码:

main.gop

import (
  "encoding/json"
  "fmt"
  "html/template"
  "io"
  "io/ioutil"
  "log"
  "net/http"
  "os"
  "strings"
)

type Hit struct {
  ID              int    `json:"id"`
  PageURL         string `json:"pageURL"`
  Type            string `json:"type"`
  Tags            string `json:"tags"`
  PreviewURL      string `json:"previewURL"`
  PreviewWidth    int    `json:"previewWidth"`
  PreviewHeight   int    `json:"previewHeight"`
  WebformatURL    string `json:"webformatURL"`
  WebformatWidth  int    `json:"webformatWidth"`
  WebformatHeight int    `json:"webformatHeight"`
  LargeImageURL   string `json:"largeImageURL"`
  FullHDURL       string `json:"fullHDURL"`
  ImageURL        string `json:"imageURL"`
  ImageWidth      int    `json:"imageWidth"`
  ImageHeight     int    `json:"imageHeight"`
  ImageSize       int    `json:"imageSize"`
  Views           int    `json:"views"`
  Downloads       int    `json:"downloads"`
  Likes           int    `json:"likes"`
  Comments        int    `json:"comments"`
  UserID          int    `json:"user_id"`
  User            string `json:"user"`
  UserImageURL    string `json:"userImageURL"`
}

type Result struct {
  Total     int   `json:"total"`
  TotalHits int   `json:"totalHits"`
  Hits      []Hit `json:"hits"`
}

func CreatePathIfNotExists(path string) {
  _, err := os.Stat(path)
  if os.IsNotExist(err) {
    os.Mkdir(path, os.ModePerm)
  }
}

func DownloadImages(w http.ResponseWriter, r *http.Request) {

  if r.Method == "GET" {
    t, _ := template.ParseFiles("downloadImages.gtpl")
    log.Println(t.Execute(w, nil))
  } else {
    err := r.ParseForm()
    if err != nil {
      log.Fatal("ParseForm: ", err)
    }

    println("key:", r.Form["key"])
    println("q:", r.Form["q"])
    println("image_type:", r.Form["image_type"])
    println("save_path:", r.Form["save_path"])

    _, keyOk := r.Form["key"]
    _, qOk := r.Form["q"]
    _, imageTypeOk := r.Form["image_type"]
    _, savePathOk := r.Form["save_path"]
    if !keyOk || !qOk || !imageTypeOk || !savePathOk {
      fmt.Fprintf(w, "请输入正确的参数")
      return
    }

    resp, err := http.Get("https://pixabay.com/api/?key=" + r.Form["key"][0] + "&q=" + r.Form["q"][0] + "&image_type=" + r.Form["image_type"][0])

    if err != nil {
      panic(err)
    }

    var res Result

    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    json.Unmarshal(body, &res)
    for i, hit := range res.Hits {
      println(i, hit.LargeImageURL)

      var iURLSplit = strings.Split(hit.LargeImageURL, "/")

      imageResp, err := http.Get(hit.LargeImageURL)

      defer resp.Body.Close()

      CreatePathIfNotExists(r.Form["save_path"][0])

      if err != nil {
        panic(err)
      }

      out, err := os.Create(r.Form["save_path"][0] + iURLSplit[len(iURLSplit)-1])
      if err != nil {
        panic(err)
      }
      defer out.Close()
      _, err = io.Copy(out, imageResp.Body)
      if err != nil {
        panic(err)
      }
    }
    fmt.Fprintf(w, "图片下载完成,下载路径为:"+r.Form["save_path"][0])
  }
}

http.HandleFunc("/", DownloadImages)     // 设置访问的路由
err := http.ListenAndServe(":8888", nil) // 设置监听的端口

if err != nil {
  log.Fatal("ListenAndServe: ", err)
}


downloadImages.gtpl

<html>
<head>
    <title>Pixabay图片下载器</title>
    <meta charset="UTF-8">
    <style>
        .a{
            width: 300px;
            height: 30px;
            margin-top: 20px;
        }
        #table{
            width: 500px;
        }
        #des{
            text-align: center;
        }
        #sub-title{
            text-align: center;
            font-size: 20px;
        }
    </style>
</head>
<body>


<center>
            <br/>
            <br/>    
<img src="https://lrting.top/wp-content/uploads/2021/11/2021111215131526.png" alt="some_text" width=500px>
            <br/>
            <br/>    
            <br/>    
            <h1>Pixabay图片下载工具</h1>            
    <div id = "sub-title">
        还在为找不到图片而发愁吗,本工具帮助你免费批量从Pixabay下载高清图片。
            <br/>
            <br/>
    </div>
    <HR align=center width=300 color=#987cb9 SIZE=1>

    <div id = "table">
        <form action="/" method="post">
            <br/>
            Pixabay申请的key
            <br/>
            <input type="text" class="a" name="key">
            <br/>
            <br/>
            搜索图片关键词
            <br/>
            <input type="text" class="a" name="q">
            <br/>
            <br/>
            图片类型
            <br/>
            <input type="text" class="a" name="image_type">
            <br/>
            <br/>
            本机保存路径
            <br/>
            <input type="text" class="a" name="save_path">
            <br/>
            <br/>
            <input type="submit" class="a" value="下载">
        </form>
    </div>
    <br/>
    <HR align=center width=300 color=#987cb9 SIZE=1>

    <div id = "des">
    </br>
    </br>
    用法:
    </br>
    </br>    
    要使用本工具,请先到Pixabay网站注册账号,注册地址:https://pixabay.com/zh/
    </br>  
    注册完之后即可在页面:https://pixabay.com/api/docs/ 查看给你分配的 API key
    </br>
    </br>    
    申请到API key之后,将其填入上述"Pixabay申请的key"方框中。
    </br>
    </br>    
    "搜索图片关键词"中输入您想要找的图片关键词,关键词与关键词之间用+连接,例如:yellow+flower
    </br>
    </br>
    "图片类型"中输入您想要找的图片的类型,可选类型为:all, photo, illustration, vector
    </br>
    </br>    
    最后输入下载的图片的本机保存路径,该工具会判断您输入的文件夹目录是否存在,如果不存在则会自动创建,例如,您可以输入windows系统中的合法地址 c:\\User\\xiaozhch5\\images\\
    </div>
</center>
</body>
</html>

一步一步看成果

运行代码:

gop run .\main.gop

浏览器打开http://localhost:8888,可以看到 

 将从https://pixabay.com/zh/注册获取到的API key、你想要下载的图片的关键词(注意是英文类型)、图片类型(可选类型为:all, photo, illustration, vector)以及图片的保存路径填入上述表单中

 点击下载即可在vscode终端看到相关下载信息:

 再查看刚刚我们输入的下载路径

 

备注:默认情况下最多会下载20张图片,如果你输入的关键词匹配的图片小于20张,那么会下载所找到的所有图片(小于20张),上述关键词(yello+flowers)找到的为5张,因为黄色拼错了哈哈哈,本来是yellow,拼成了yello了。

打成exe文件

最后,可以把这个工程打包成一个exe项目,这样子我每次抓取图片就不需要打开vscode就可以啦。

执行:

gop build .

在当前目录下生成go+.exe文件,双击可直接运行。

然后同样在浏览器中输入http://localhost:8888可同样进入如下页面

下载体验

有兴趣的同学可以直接下载我构建好的exe文件,文件链接为:

https://github.com/xiaozhch5/gop-image-capture/releases/download/1.0-release/1.0-release.zip

或者访问我的完整代码:

https://github.com/xiaozhch5/gop-image-capture

 

 

...全文
438 8 打赏 收藏 举报
写回复
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ζ小菜鸡 2021-12-10
  • 打赏
  • 举报
回复
大佬,膜拜膜拜
BigDataToAI 社区中级贡献者 2021-12-10
  • 举报
回复
@ζ小菜鸡 也是刚刚学习,多多指教
静仪Coco 2021-12-08
  • 打赏
  • 举报
回复
超级棒👍🏻٩(•̤̀ᵕ•̤́๑)ᵒᵏᵎᵎᵎᵎ
BigDataToAI 社区中级贡献者 2021-12-08
  • 举报
回复
@静仪Coco 多多指教
红目香薰 社区中级贡献者 2021-12-08
  • 打赏
  • 举报
回复

这个可以有。

BigDataToAI 社区中级贡献者 2021-12-08
  • 举报
回复
@红目香薰 多多指教
叶庭云 社区初级贡献者 2021-12-08
  • 打赏
  • 举报
回复

这个强,给你点赞。

BigDataToAI 社区中级贡献者 2021-12-08
  • 举报
回复
@叶庭云 刚好解决了最近图片荒
相关推荐
发帖
Go+ 开发者社区

906

社区成员

Go+ 官方开发者社区。我们希望向广大的开发者和数据科学家介绍 Go+ 的定位和意义,并邀请更多开发者一起贡献代码、共建 Go+ 生态。 Go+ 官网:https://goplus.org/
其他 企业社区
社区管理员
  • Go+
  • 杨东杰
加入社区
帖子事件
创建了帖子
2021-12-08 02:19
社区公告

本社区为 Go+ 官方开发者社区。我们希望向广大的开发者和数据科学家介绍 Go+ 的定位和意义,并邀请更多开发者一起贡献代码、共建 Go+ 生态。

Go+ 官网:https://goplus.org/
GitHub地址:https://github.com/goplus/gop