背景

想获取bing历史壁纸。

目标

获取到bing历史壁纸。

步骤

访问 https://www.bing.com/HPImageArchive.aspx?format=js&n=1 可以获取当天的bing壁纸。
调整n的值可以获取更多,但最多只能有8个。

无意间看到必应每日图片、私有图床壁纸查询Api - 学习 - Timeless提供的接口,免费,可直接调用。就有了如下代码。

如下共4个文件,代码基于springboot-2.2.10。

value object对象

package cn.example.bingimg;

import lombok.Data;

import java.io.Serializable;

/**
 * 必应图片接口外层响应类
 */
@Data
public class BingImageResponse implements Serializable {
    /**
     * 错误码(0表示成功)
     */
    private Integer errno;

    /**
     * 错误信息(成功时为空)
     */
    private String errmsg;

    /**
     * 分页数据(核心数据)
     */
    private BingImagePageData data;
}
package cn.example.bingimg;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * 必应图片分页数据类
 */
@Data
public class BingImagePageData implements Serializable {
    /**
     * 图片总条数
     */
    private Integer count;

    /**
     * 总页数
     */
    private Integer totalPages;

    /**
     * 每页条数
     */
    private Integer pageSize;

    /**
     * 当前页码
     */
    private Integer currentPage;

    /**
     * 图片列表(内层数据)
     */
    private List<BingImageInfo> data;
}
package cn.example.bingimg;

import lombok.Data;

import java.io.Serializable;

/**
 * 必应图片详情信息类
 */
@Data
public class BingImageInfo implements Serializable {
    /**
     * 图片唯一ID(MongoDB风格ID)
     */
    private String _id;

    /**
     * 图片标题
     */
    private String title;

    /**
     * 图片版权信息(含来源和作者)
     */
    private String copyright;

    /**
     * 图片完整URL(可直接访问)
     */
    private String url;

    /**
     * 图片基础URL(不含尺寸参数)
     */
    private String urlbase;

    /**
     * 图片日期(格式:yyyy-MM-dd)
     */
    private String time;
}

测试方法入口

package cn.example;

import cn.example.bingimg.BingImageInfo;
import cn.example.bingimg.BingImagePageData;
import cn.example.bingimg.BingImageResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;

/**
 * .
 *
 * @since 2025-10-28
 */
@Slf4j
public class BingImageGather {
    final RestTemplate restTemplate = new RestTemplate();

    @Test
    public void doGather() throws IOException {
        String url = "https://api.timelessq.com/bing/list?&pageSize=10&page=";
        int page = 1;
        for (; ; ) {
            BingImageResponse response = restTemplate.getForObject(url + page, BingImageResponse.class);
            if (Objects.isNull(response)) {
                break;
            }
            Integer errno = response.getErrno();
            if (!Integer.valueOf(0).equals(errno)) {
                log.warn("errno:{}", response.getErrmsg());
                break;
            }
            BingImagePageData data = response.getData();
            List<BingImageInfo> imageList = data.getData();
            if (CollectionUtils.isEmpty(imageList)) {
                break;
            }
            downloadImages(imageList);
            page++;
        }

    }


    /**
     * 使用RestTemplate下载图片,返回字节数组
     */
    private static byte[] downloadImage(RestTemplate restTemplate, String imageUrl) {
        // 自定义响应提取器,将响应流转换为字节数组
        ResponseExtractor<byte[]> responseExtractor = new ResponseExtractor<byte[]>() {
            @Override
            public byte[] extractData(ClientHttpResponse response) throws IOException {
                // 读取响应输入流到字节数组
                try (InputStream in = response.getBody();
                     ByteArrayOutputStream out = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int len;
                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    return out.toByteArray();
                }
            }
        };

        // 发送GET请求,提取响应体字节数组
        return restTemplate.execute(imageUrl, HttpMethod.GET, null, responseExtractor);
    }

    private void downloadImages(List<BingImageInfo> imageList) throws IOException {
        for (BingImageInfo bingImageInfo : imageList) {
            String url = bingImageInfo.getUrl();
            byte[] imageBytes = downloadImage(restTemplate, url);
            UriComponents components = UriComponentsBuilder.fromUriString(url).build();
            String filename = components.getQueryParams().getFirst("id");
            FileUtils.writeByteArrayToFile(new File("x:/bing/" + filename), imageBytes);
        }
    }
}

收工。