每日自动获取必应搜索背景图、微软锁屏背景图

1,167 阅读5分钟

这是我参与更文挑战的第 24 天,活动详情查看:更文挑战

今天想换个桌面壁纸,一直没找到合适的,后来在盯着电脑锁屏发呆的时候,突然觉得锁屏的图片还挺好看的,就萌发了写个程序将每天锁屏的图片保存下来作为桌面壁纸的想法。另外还联想到了必应搜索的背景图片,也是挺不错的,就一起实现了吧。

保存微软锁屏背景

首先找到微软锁屏图片的文件存放路径,简单查询了一下发现是在这个文件夹:

C:\Users\LvLin\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets

这是我的本地路径,由于每个人的用户名不一样,路径也会有所差异,这点需要注意。另外就是这些图片文件默认都没有后缀名,我们可以给其中几个加个图片格式后缀名看看效果:

Snipaste_2021-06-24_22-02-07.png

能够看到每张图片都分了横屏跟竖屏两种规格,在实现的时候我们只要横屏规格的图片。

简单捋一下要实现的代码逻辑:

  1. 读取锁屏图片目录下的所有文件;
  2. 筛选出横屏规格的图片;
  3. 加上相应的后缀名,保存到目标文件夹下。

然后开干。创建项目文件夹getImg,初始化项目:

> npm init -y

创建一个img文件夹用于存储图片。目标代码写在getImgFromLScreen.js文件中。

先安装一个npm包,用于判断图片的宽高,实现图片规格筛选:

> npm i --save image-size

getImgFromLScreen.js代码内容如下所示:

// 1. 读取微软锁屏图片目录下的所有文件;
// 2. 筛选出横屏规格的图片;
// 3. 加上相应的后缀名,保存到目标文件夹下。
const fs = require('fs/promises');
const sizeOf = require('image-size');
var os = require('os');

const username = os.userInfo().username; // 获取用户名
const LScreenFilePath = `C:\\Users\\${username}\\AppData\\Local\\Packages\\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\\LocalState\\Assets\\`;

/**
 * 
 * @param {String} savePath 目标存储路径,默认为项目下的 img 文件夹,可以传输一个绝对路径
 * @param {String} filePath 微软锁屏图片所在目录,默认为 C:\Users\%username%\AppData\Local\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets\
 */
async function getImgFromLScreen(savePath = '.\\img\\', filePath = LScreenFilePath) {
    try {
        // 获取到文件夹下所有的文件列表
        let dir = await fs.readdir(filePath);
        let dimensions, fileName;
        
        // 循环遍历文件列表,进行规格筛选
        for (let i = 0; i < dir.length; i++) {
            fileName = dir[i];
            dimensions = sizeOf(filePath + fileName);

            // 通过宽高的比值,筛选出横屏规格的图片
            if (dimensions.width > dimensions.height) {
                // 将图片复制到目标路径
                saveImg(filePath, fileName, savePath, dimensions.type);
            }
        }
    } catch (err) {
        console.error(err.message);
    }
}

/**
 * 将图片复制到目标路径
 * 
 * @param {String} filePath 锁屏文件所在路径
 * @param {String} fileName 锁屏背景图文件名
 * @param {String} savePath 目标路径
 * @param {String} imgType  锁屏背景图格式,用于添加文件后缀名
 */
function saveImg(filePath, fileName, savePath, imgType) {
    try {
        fs.copyFile(filePath + fileName, savePath + fileName +'.'+ imgType);
    } catch (error) {
        console.error(err.message);
    }
} 

// 导出该模块
module.exports = getImgFromLScreen;

创建一个index.js入口文件,执行该模块代码:

const getImgFromLScreen = require('./getImgFromLScreen');

getImgFromLScreen();

运行index.js,查看效果:

> node index.js

image.png

nice!!!

获取必应搜索背景图片

接下来我们看必应搜索的北京图片应该怎么获取。

打开必应搜索页面,通过Network面板,可以看到获取图片路径的接口,去掉一些环境相关的参数,得到的接口路径为https://cn.bing.com/HPImageArchive.aspx?format=js&n=1,获取到的数据格式如下:

{
    "images": [
        {
            ...
            "url": "/th?id=OHR.DenaliCaribou_ZH-CN9804350098_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
            ...
        }
    ],
    "tooltips":{...}
}

images.url拼接上https://cn.bing.com就是我们需要的图片路径,将其中1920x1080换成UHD,去掉?后面的参数,就能够得到高清的背景图片地址哦。

简单捋一下获取必应搜索背景图片的代码逻辑:

  1. 访问必应相关接口,获取图片的相对路径;
  2. 根据规则拼接出图片的访问路径;
  3. 访问获取图片,存储到目标文件夹。

在刚刚的项目中增加一个文件getImgFromBiYing.js,内容与解释如下所示:

// 通过发送请求,获取必应的背景图片,并存到本地文件夹
// 接受一个参数,作为图片保存的路径,默认存在 C:\image
// 使用必应官方接口 https://cn.bing.com/HPImageArchive.aspx?format=js&n=1

const https = require('https');
const fs = require('fs');

/**
 * 1. 访问必应相关接口,获取图片的相对路径;
 * 2. 根据规则拼接出图片的访问路径;
 * 3. 访问获取图片,存储到目标文件夹。
 * 
 * @param {String} filePath 
 */
function getImgFromBiYing(filePath = '.\\img\\') {
    const options = {
        hostname: 'cn.bing.com',
        port: 443,
        path: '/HPImageArchive.aspx?format=js&n=1',
        method: 'GET'
    };

    // 请求接口获取图片的路径信息
    const req = https.request(options, res => {
        res.on('data', data => {
            try {
                let obj = JSON.parse(data.toString());
                let url = obj.images[0].url;
                // 换成高清规格的图片路径,并去掉多余参数
                let imgUrl = url.split('&')[0].replace('1920x1080', 'UHD');
                // 得到图片文件名称
                let fileName = imgUrl.replace('/th?id=', '');

                // 获取图片资源并保存图片
                saveImg(imgUrl, filePath + fileName);
            } catch (error) {
                process.stdout.write(error);
            }
        });
    });

    req.on('error', error => {
        console.error(error);
    });

    req.end();
}

/**
 * 将图片存储到目标文件夹
 * 
 * @param {String} path 
 * @param {String} fileName 
 */
function saveImg(path, fileName) {
    const options = {
        hostname: 'cn.bing.com',
        port: 443,
        path,
        method: 'GET'
    };

    const req = https.request(options, res => {
        let imgData = '';
        res.setEncoding("binary");
        // 请求图片资源,存入 imgData 中
        res.on('data', chunk => {
            imgData += chunk;
        });

        res.on('end', () => {
            try {
                // 将图片写入目标文件夹
                fs.writeFile(fileName, imgData, 'binary', err => {
                    if (err) {
                        console.error(err.message)
                        return
                    }
                })
            } catch (error) {
                console.error(error.message);
            }
        })
    });

    req.on('error', error => {
        console.error(error.message);
    });

    req.end();
}

// 导出模块
module.exports = getImgFromBiYing;

修改index.js文件:

const getImgFromLScreen = require('./getImgFromLScreen');
const getImgFromBiYing = require('./getImgFromBiYing');

getImgFromBiYing();
getImgFromLScreen();

运行index.js,查看获取的图片。

image.png

背景配置

index.js文件进行加工,让程序能够每天运行一次,自动拉取新文件。

const getImgFromLScreen = require('./getImgFromLScreen');
const getImgFromBiYing = require('./getImgFromBiYing');

// 每 12 小时拉取一次
setInterval(()=>{
    getImgFromBiYing();
    getImgFromLScreen();
    console.log(new Date() + ':已拉取最新的必应背景图跟微软锁屏图')
}, 12*3600*1000)

最后,进入windows的个性化设置,将存储图片的文件夹设置成我们的背景图目录,选择幻灯片放映模式。

image.png

每天动态切换的桌面壁纸 get ✔~

最后

有没有可以继续优化的地方呢,欢迎评论区说出你的想法~

觉得文章不错的话,求赞~