我的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

 

 

...全文
2017 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
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
  • 举报
回复
@叶庭云 刚好解决了最近图片荒
内容概要:本文档是一份针对初学者的Spring框架整合学习笔记,系统介绍了Spring Framework的核心基础与Spring MVC的开发应用。内容涵盖IOC(控制反转)的基本概念、配置方式与注解使用,详细讲解了bean的生命周期、作用域、依赖注入方式及自动装配机制;深入阐述AOP(面向切面编程)的XML与注解实现,包括切点、通知、织入等核心概念;全面演示Spring MVC的环境搭建、请求处理、参数绑定、视图解析、文件上传、RESTful风格支持、JSON返回、异常处理与拦截器开发;同时包含表单验证、国际化、与Struts2对比以及Spring IOC与MVC整合等实用知识点。; 适合人群:具备Java基础和基本Web开发经验,正在学习或刚进入企业级Java开发领域的初级程序员、应届毕业生及转行人员。; 使用场景及目标:①掌握Spring核心机制如IOC、AOP的原理与实际配置;②能够独立搭建Spring MVC项目并实现常见Web功能如参数接收、响应处理、文件上传、异常统一管理等;③理解Spring生态中各注解的作用与最佳实践,为后续学习Spring Boot和微服务打下坚实基础。; 阅读建议:此资源以理论结合实操为主,建议边阅读边动手搭建项目,重点理解配置背后的运行机制,尤其是bean生命周期、AOP织入过程和MVC请求流程,配合调试加深理解。
内容概要:本文围绕2026年高教社杯全国大学生数学建模竞赛A题“药材的烘干问题”提供完整的数学建模解决方案,涵盖问题分析、模型构建、算法实现与论文撰等全套资源。文档不仅深入解析药材烘干过程中的传热传质机理,建立优化模型以提升干燥效率与品质,还系统整合了Matlab、Python等多种编程语言代码实现方案,并附有高质量论文模板与作指导。此外,资源包扩展覆盖无线电干扰源定位、微网电力调控、时频冲突消解、SEM广告投放策略等多个赛题,以及信号处理、电力系统优化、车间调度、路径规划、图像处理等多领域科研技术支持,配套提供大量仿真代码、算法模型与网盘资源链接,形成面向数学建模竞赛与科研实践的一站式学习与应用平台。; 适合人群:全国大学生数学建模竞赛参赛者,具备一定数学建模、编程基础的本科及研究生层次学生,以及从事智能优化、信号处理、电力系统、路径规划等相关领域的科研人员与工程技术人员。; 使用场景及目标:①辅助完成数学建模竞赛题目,特别是药材烘干过程的建模与优化求解;②学习多领域典型问题的建模方法与算法实现技巧,如优化算法、机器学习、控制仿真等;③获取标准化论文作框架与优秀范例,提升科研表达能力与竞赛成绩。; 阅读建议:建议结合文档中提供的代码与论文范例进行实操复现,重点掌握建模逻辑、算法选型与结果分析方法;充分利用网盘资源拓展学习广度,针对自身研究方向深入钻研相关技术细节,全面提升综合实践与创新能力。
内容概要:本文系统阐述了基于矩方法的工程不确定度快速评估策略,重点突出其在迭代设计优化中的计算效率与稳定性优势,并配套提供了完整的Matlab代码实现。该方法通过提取输入变量的高阶矩信息,结合最大熵原理进行概率分布重建,从而实现对输出响应不确定性的高效传播分析,有效克服了传统蒙特卡洛方法计算成本高昂的弊端。研究深入对比了最大熵方法与Pearson分布系统在处理单峰及多峰分布尾部估计时的性能差异,验证了前者在扩展不确定度评估中的更高精度与更强鲁棒性,尤其适用于航空航天、高端装备等对可靠性要求严苛的复杂工程系统。; 适合人群:具备概率统计、随机过程及数值计算基础,从事工程设计、可靠性分析、不确定性量化或优化研究的科研人员、工程师及高年级研究生。; 使用场景及目标:①解决复杂工程系统中因材料、制造、载荷等多源不确定性引发的性能波动评估难题;②在迭代式设计优化流程中嵌入高效的不确定度传播模块,提升优化过程的稳定性与收敛性;③替代计算耗时的抽样方法(如蒙特卡洛),实现快速风险评估与可靠性分析;④应用于高维、非线性系统的尾部风险预测与安全边界划定。; 阅读建议:建议读者结合提供的Matlab代码,重点研读高阶矩计算、矩约束构建、熵最大化优化求解及概率密度函数重建等关键模块的实现细节,通过复现文中的对比实验,深入理解不同方法在尾部估计上的差异,并尝试将其应用于自身的工程案例中以掌握其适用边界与调参技巧。
代码下载链接: https://pan.quark.cn/s/a4b39357ea24 【JAVA 个人版电影院售票管理系统】是一项依托于NetBeans开发平台构建的应用项目,其目标在于模仿现实中的电影院售票过程,致力于提供高效且方便的票务管理解决方案。该系统全面包含了电影排期安排、座位预定管理以及购票支付处理等一连串功能,为使用者和管理者提供了直观易用的交互平台。 1. **Java编程语言**:该系统的核心构建工具是Java,它作为一种跨操作系统的面向对象编程语言,拥有丰富的类库资源和卓越的性能表现,非常适合用于开发此类桌面应用程序。 2. **NetBeans IDE**:NetBeans是一个开源性质的集成开发工具,能够支持Java、C++等多种编程语言的开发工作,提供了从代码、调试、测试到部署的全方位服务,有效简化了项目的构建与维护流程。 3. **MVC设计模式**:模型-视图-控制器(Model-View-Controller)的设计理念被广泛采纳于该系统中,实现了业务逻辑、数据操作和用户界面的分离处理,从而形成了条理清晰的代码架构,便于后续的维护和功能扩展。 4. **数据库管理**:系统可能运用了SQLite或MySQL这类关系型数据库来储存电影资讯、演出时间表、座位可用状态以及购票历史等数据,达成了数据的持久化保存和高效率查询的目标。 5. **用户界面**:系统需具备视觉吸引力且操作简便的用户界面,涵盖电影信息列表呈现、场次挑选、座位分布图示、订单确认及支付环节等,这些界面通常借助Java Swing或JavaFX库来实现视觉呈现。 6. **数据验证**:在用户输入信息阶段,系统将执行数据校验操作,保证输入的电影名称、演出场次、座位...

1,097

社区成员

发帖
与我相关
我的任务
社区描述
Go+ 官方开发者社区。我们希望向广大的开发者和数据科学家介绍 Go+ 的定位和意义,并邀请更多开发者一起贡献代码、共建 Go+ 生态。 Go+ 官网:https://goplus.org/
其他 企业社区
社区管理员
  • Go+
  • 杨东杰
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

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

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

试试用AI创作助手写篇文章吧