每天定時獲取必應每日一圖並保存做壁紙

每天定時獲取必應每日一圖並保存做壁紙

​ 必應每天會更新每日一圖,這些圖片都是特別好看,適合做封面壁紙等等。我做了一個自動腳本,讓它每天定時獲取每日一圖,然後設置爲個人主頁博客的封面,封面和背景一共九張圖片,每天更新後以隊列的順序替換。

​ 這裏是成品:個人搭建的博客主頁

獲取每日一圖的鏈接

從接口獲取鏈接

必應提供了一個獲取每日一圖的接口,https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1,訪問此接口會返回一個json數據,數據如下:

{
    "images": [
        {
            "startdate":"20201116",
            "fullstartdate":"202011161600",
            "enddate":"20201117",
            "url":"/th?id=OHR.MischwaldFuessen_ZH-CN0005213724_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
            "urlbase":"/th?id=OHR.MischwaldFuessen_ZH-CN0005213724",
            "copyright":"混交林,菲森,巴伐利亞,德國 (© Erich Kuchling/DEEPOL by plainpicture)",
            "copyrightlink":"https://www.bing.com/search?q=%E6%B7%B7%E4%BA%A4%E6%9E%97&form=hpcapt&mkt=zh-cn",
            "title":"",
            "quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20201116_MischwaldFuessen%22&FORM=HPQUIZ",
            "wp":true,
            "hsh":"8df6576dae2e935290a0f48ff9ab10bb",
            "drk":1,
            "top":1,
            "bot":1,
            "hs":[]
        }
    ],
    "tooltips":{
        "loading":"正在加載...",
        "previous":"上一個圖像",
        "next":"下一個圖像",
        "walle":"此圖片不能下載用作壁紙。",
        "walls":"下載今日美圖。僅限用作桌面壁紙。"
    }
}

上面的json數據中的images中url的value就是當天圖片的地址的一半,還需要添加一個前綴https://www.bing.com/或者http://s.cn.bing.net,兩者選其一,比如今天的圖片完整鏈接爲https://www.bing.com//th?id=OHR.MischwaldFuessen_ZH-CN0005213724_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp,下載的圖片格式爲jpeg。

使用Java得到鏈接

知道了圖片的鏈接獲取方法,就寫一個Java程序來獲取它。我們將頁面的json數據一行一行讀取,存入一個字符串並返回。

public static String getURLContent(String urlStr) {
    //請求的url
    URL url = null;
    //建立的http鏈接
    HttpURLConnection httpConn = null;
    //請求的輸入流
    BufferedReader in = null;
    //輸入流的緩衝
    StringBuffer sb = new StringBuffer();
    try{
        url = new URL(urlStr);
        in = new BufferedReader(new InputStreamReader(url.openStream(),"UTF-8") );
        String str = null;
        //一行一行進行讀入
        while((str = in.readLine()) != null) {
            sb.append( str );
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally{
        try{
            if(in!=null) {
                in.close(); //關閉流
            }
        }catch(IOException ex) {
            ex.printStackTrace();
        }
    }
    String result =sb.toString();
    return result;
}

返回值就是上述的json數據的字符串形式,然後我們使用阿里的一個處理json數據的庫來簡化操作,在pom.xml文件中加入下面的依賴:

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.73</version>
</dependency>

利用這個工具將String類型的json數據封裝成一個JSONObject,通過調用get(key)或者getString(key)獲取到key對應的value,因爲這個json數據裏面有級聯屬性,所以先獲取images對應的value。

//通過該鏈接先獲取到json數據的字符串形式
String urlContent = getURLContent("https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1");
//將json數據封裝成json對象
JSONObject jsonObject = JSONObject.parseObject(urlContent);
// 獲取到key爲images的值
String r = jsonObject.getString("images");

這時候的r字符串就是

[
    {
        "startdate":"20201116",
        "fullstartdate":"202011161600",
        "enddate":"20201117",
        "url":"/th?id=OHR.MischwaldFuessen_ZH-CN0005213724_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp",
        "urlbase":"/th?id=OHR.MischwaldFuessen_ZH-CN0005213724",
        "copyright":"混交林,菲森,巴伐利亞,德國 (© Erich Kuchling/DEEPOL by plainpicture)",
        "copyrightlink":"https://www.bing.com/search?q=%E6%B7%B7%E4%BA%A4%E6%9E%97&form=hpcapt&mkt=zh-cn",
        "title":"",
        "quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20201116_MischwaldFuessen%22&FORM=HPQUIZ",
        "wp":true,
        "hsh":"8df6576dae2e935290a0f48ff9ab10bb",
        "drk":1,
        "top":1,
        "bot":1,
        "hs":[]
    }
]

爲了方便起見,直接截取字符串的1到r.length()-1的內容,繼續將其封裝爲json對象,然後進而獲取它url對應的value

r = r.substring(1,r.length()-1);
jsonObject = JSONObject.parseObject(r);
String url = jsonObject.getString("url");

這時候拿到的value就是我們要的鏈接的後綴/th?id=OHR.MischwaldFuessen_ZH-CN0005213724_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp,只需要將其和前綴拼接在一起即可作爲圖片的地址。我們先將地址保存在一個文件裏面,文件起名叫link

String result = "https://www.bing.com/" + url;
File file = new File("./link");
if (!file.exists()) {
    file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(result.getBytes());

到此,Java程序完成,執行此程序即可將當日的每日一圖的地址存入link這個文件裏。

使用shell腳本將圖片下載到制定位置

思路很簡單,使用shell腳本調用Java程序,然後去link文件中拿到鏈接即可使用wget命令進行下載。

將Java程序打包成一個jar包

由於我們這個項目加入了阿里巴巴處理json的以來,所以需要帶着依賴打包。

點擊File->Project Structure->Artifacts->Jar->From modules with dependencies

點擊OK->Apply->關閉。這時候就在src下生成了一個.MF文件

點擊Build->Build Artifacts

這時候就在項目目錄下的out目錄裏生成了可執行jar包,執行java -jar xxx.jar命令即可運行此程序,即在link中寫入當日每日一圖的鏈接地址。但是實際運行的時候發現報了一個錯誤GetPic.jar中沒有主清單屬性

用Ark(一個壓縮工具)打開jar包,然後打開裏面的META-INF/MANIFEST.MF,查看是否有Main-Class項,估計是沒有,然後加入一行Main-Class: GetPic其中GetPic爲主類名。注意Main-Class:和GetPic之間有一個空格。

這樣運行jar包就可以成功了,成功將當日每日一圖的地址寫入link文件中。

下載圖片到指定位置

使用下面的命令可以將link中的鏈接取出來作爲wget的下載鏈接,使用-O選項給圖片指定地址並命名,命名爲當天的日期。

wget `cat link` -O ./pic/$(date "+%Y%m%d").jpeg

所以完整的shell腳本如下:

#!/bin/bash
java -jar GetPic.jar
wget `cat link` -O ./pic/$(date "+%Y%m%d").jpeg

手動執行腳本完成對圖片的下載。

啓動定時任務

既然是每日一圖,那就應該每天定時去獲取這個圖片,利用linux的crontab工具可以實現這一需求。

先檢查crond服務是否正常啓動:

service cron status

然後將這個腳本加入到定時計劃中,這個是指定每天早上6點下載一次

0 6 * * * sh ~/zhangqi/getPic/getPic.sh

然後就開始等待第二天的6點,結果執行失敗。

分析原因&解決問題

我們手動執行這個腳本成功下載到了文件,但加到定時任務裏執行失敗,分析有以下幾個可能的原因:

  1. 定時任務沒有成功啓動
  2. shell裏面某個任務沒有成功啓動

爲了排除第一個可能的錯誤,寫了一個每分鐘輸出hello world到日誌文件的命令後,發現定時任務成功啓動,這樣就排除了第一種可能。這樣一來就說明shell裏面某些任務沒有啓動。

先試着測試第一個執行jar包的命令,發現執行失敗,然後將執行這個jar包換成了一個Hello Word的程序,發現還是失敗。推測可能是Java程序執行出錯,但手動確實正常執行。去網上查到一個帖子說crontab不會知道你腳本里需要用到的所有環境變量,突然就明白是沒有指明環境變量,腳本中直接使用Java命令失敗導致的錯誤。在腳本中輸出$JAVA_HOME果然沒有結果。

找到問題後就明確方向了,在腳本開頭引入環境變量

#!/bin/bash
. /etc/profile
java -jar GetPic.jar
if [ $? -eq 0 ]; then
    echo 'success' >> ./log.txt
else
    echo 'jar包運行出錯' >> ./log.txt
    exit
fi
wget `cat link` -O ./pic/$(date "+%Y%m%d").jpeg

再次測試發現還是出錯,但這次輸出$JAVA_HOME成功,說明並不是環境變量的問題,仔細考慮了下懷疑是路徑的問題,在腳本中輸出pwd到日誌發現確實如此,然後加上一句cd命令。

#!/bin/bash
. /etc/profile
cd /home/ubuntu/zhangqi/getPic
java -jar GetPic.jar
if [ $? -eq 0 ]; then
    echo 'success' >> ./log.txt
else
    echo $JAVA_HOME >> ./log.txt
    exit
fi
wget `cat link` -O ./pic/$(date "+%Y%m%d").jpeg

至此,運行成功。最後加上日誌信息,方便萬一以後出錯來debug。然後根據自己想要的用途來使用這些精美圖片即可。

#!/bin/bash
. /etc/profile
cd /home/ubuntu/zhangqi/getPic
java -jar GetPic.jar
echo $(date "+%Y-%m-%d-%H-%M-%S") >> ./log.txt
if [ $? -eq 0 ]; then
    echo 'success to getUrl' >> ./log.txt
else
    echo 'jar包執行錯誤,檢查該鏈接還是否正確https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1' >> ./log.txt
    exit
fi
wget `cat link` -O ./pic/$(date "+%Y%m%d").jpeg
if [ $? -eq 0 ]; then
    echo 'success to download' >> ./log.txt
else
    echo '下載失敗,檢查網絡和下載鏈接' >> ./log.txt
    cat link >> ./log.txt
    exit
fi
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章