实现方法来自:利用Api获取必应的每日一图
接口分析
主要api是:
https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1
响应体如下:
{
"images": [
{
"startdate": "20240229",
"fullstartdate": "202402291600",
"enddate": "20240301",
"url": "/th?id=OHR.Schmetterlingswiese_ZH-CN3740804088_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
"urlbase": "/th?id=OHR.Schmetterlingswiese_ZH-CN3740804088",
"copyright": "德国草地上的蝴蝶 (© Albert Fertl/Getty Images)",
"copyrightlink": "https://www.bing.com/search?q=%E8%9D%B4%E8%9D%B6&form=hpcapt&mkt=zh-cn",
"title": "蝶舞翩跹",
"quiz": "/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20240229_Schmetterlingswiese%22&FORM=HPQUIZ",
"wp": true,
"hsh": "00894a0ae6a40ff698e21ce2afdd33eb",
"drk": 1,
"top": 1,
"bot": 1,
"hs": []
}
],
"tooltips": {
"loading": "正在加载...",
"previous": "上一个图像",
"next": "下一个图像",
"walle": "此图片不能下载用作壁纸。",
"walls": "下载今日美图。仅限用作桌面壁纸。"
}
}
主要业务逻辑实现
package service
import (
"encoding/json"
"io"
"log"
"net/http"
"time"
)
// from page :https://cloud.tencent.com/developer/article/2086721
type BingImage struct {
Bot int `json:"bot"`
Copyright string `json:"copyright"`
CopyrightLink string `json:"copyrightlink"`
Drk int `json:"drk"`
EndDate string `json:"enddate"`
FullStartDate string `json:"fullstartdate"`
Hs []int `json:"hs"`
Hsh string `json:"hsh"`
Quiz string `json:"quiz"`
StartDate string `json:"startdate"`
Title string `json:"title"`
Top int `json:"top"`
Url string `json:"url"`
UrlBase string `json:"urlbase"`
Wp bool `json:"wp"`
}
type BingToolTips struct {
Loading string `json:"loading"`
Next string `json:"next"`
Previous string `json:"previous"`
WallE string `json:"walle"`
WallS string `json:"walls"`
}
type BingResponse struct {
Images []BingImage `json:"images"`
Tooltips BingToolTips `json:"tooltips"`
}
type Picture struct {
Title string `json:"title"`
URL string `json:"url"`
Copyright string `json:"copyright"`
}
var picture *Picture
var lastTime time.Time
func GetPicture() *Picture {
if picture != nil && isToday(lastTime) {
return picture
}
lastTime = time.Now()
picture = getNewPicture()
return picture
}
func isToday(t time.Time) bool {
now := time.Now() // 获取当前时间
return t.Year() == now.Year() && t.Month() == now.Month() && t.Day() == now.Day()
}
func getNewPicture() *Picture {
resp, err := http.Get("https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1")
if err != nil {
log.Fatal(err)
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Fatal(err)
}
}(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
response := BingResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
log.Fatal(err)
}
if len(response.Images) > 0 {
image := response.Images[0]
return &Picture{
Title: image.Title,
Copyright: image.Copyright,
URL: "https://www.bing.com" + image.Url,
}
}
return nil
}
说明:
- 结构体的属性名首字母均为大写,因为涉及到Json的序列化,首字母小写在Golang中意味着“私有”,私有的属性无法完成序列化。
- picture声明为指针类型,主要是保证全局只存在一份数据,也方便做缓存
对外暴露接口
r.GET("/image", func(context *gin.Context) {
context.PureJSON(200, service.GetPicture())
})
说明:
- 这个地方使用的是
context.PureJson()
,其主要原因是context.Json()
会对参数中的特殊字符进行转义,接口中的&
字符转义后图片地址将无法正常访问。而PureJson()
则可原封不动的将数据返回。