如何使用 Github Actions 自動抓取每日必應壁紙?


點贊再看,動力無限。Hello world : ) 微信搜「 程序猿阿朗 」。

本文 Github.com/niumoo/JavaNotes未讀代碼博客 已經收錄,有很多知識點和系列文章。

如何白嫖 Github 服務器自動抓取必應搜索的每日壁紙呢?

如果你訪問過必應搜索網站,那么你一定會被搜索頁面的壁紙吸引,必應搜索的壁紙每日不同,自動更換,十分精美。這篇文章會介紹如何一步步分析出必應搜索壁紙 API ,如何結合 Github Actions自動抓取每日必應壁紙到 Github 倉庫。

元宵節當天具有中國元素的必應搜索。

必應搜索主頁

平常一天的必應搜索。

必應首頁

分析必應壁紙 API

既然是網站上的背景,又是每天更換,很大概率是通過某個 API 請求返回壁紙信息的,事實真是如此嗎?直接打開瀏覽器 network 控制台監控網絡請求信息。

分析必應壁紙API

篩選 XHR 異步請求,排除 js 文件加載請求后,在一個路徑為 HPImageArchive.aspx 的請求中,發現響應的信息似乎和背景圖片有關,直接復制出請求的 URL ,得到了一個似乎是壁紙 API 的接口。

https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=1614319565639&pid=hp&FORM=BEHPTB&uhd=1&uhdwidth=3840&uhdheight=2160

這個接口返回的信息到底是不是頁面上的圖片信息呢?還需要進一步測試,單獨請求分析這個接口,分析其中的響應信息。

➜  ~ curl https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=1614319565639&pid=hp&FORM=BEHPTB&uhd=1&uhdwidth=3840&uhdheight=2160
{
  "images": [
    {
      "startdate": "20210225",
      "fullstartdate": "202102251600",
      "enddate": "20210226",
      "url": "/th?id=OHR.JinliStreet_ZH-CN3020276206_UHD.jpg&rf=LaDigue_UHD.jpg&pid=hp&w=3840&h=2160&rs=1&c=4",
      "urlbase": "/th?id=OHR.JinliStreet_ZH-CN3020276206",
      "copyright": "掛在錦里街上的紅燈籠,中國成都 (© Philippe LEJEANVRE/Getty Images)",
      "copyrightlink": "/search?q=%e9%94%a6%e9%87%8c%e8%a1%97&form=hpcapt&mkt=zh-cn",
      "title": "",
      "quiz": "/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20210225_JinliStreet%22&FORM=HPQUIZ",
      "wp": true,
      "hsh": "e9b5fb1ad61034342e8d459bff8fc5c5",
      "drk": 1,
      "top": 1,
      "bot": 1,
      "hs": []
    }
  ],
  "tooltips": {
    "loading": "正在加載...",
    "previous": "上一個圖像",
    "next": "下一個圖像",
    "walle": "此圖片不能下載用作壁紙。",
    "walls": "下載今日美圖。僅限用作桌面壁紙。"
  }
}
➜  ~

可以看到返回的結果中有 URL 信息,拼接到必應網址訪問測試(其實通過響應信息里的圖片描述 ”掛在錦里街上的紅燈籠,中國成都“ 就已經猜到大概率是了,今日元宵節)。

https://bing.com/th?id=OHR.JinliStreet_ZH-CN3020276206_UHD.jpg&rf=LaDigue_UHD.jpg&pid=hp&w=3840&h=2160&rs=1&c=4

訪問后發現就是必應搜索網站的當日壁紙(元宵節必應放了一張紅色燈籠壁紙)。

元宵節

到這里,我們已經找到了必應搜索壁紙的 API 接口和響應信息中的圖片地址。如果再看圖片的 URL 地址,其中攜帶了不少參數,這些參數是什么意思呢?可以大膽猜測,其中的參數 w=3840&h=2160 應該是指圖片的寬和高,確實是這樣,調整這兩個參數可以返回不同分辨率的圖片,如果沒有這兩個參數就可以返回超清原圖。

必應壁紙爬蟲

上面分析出了必應壁紙的 API ,那么就不難寫一個自動爬取當天必應壁紙的自動化程序。

  1. 請求必應壁紙 API。
  2. JSON 解析出圖片 URL。

這里網絡請求使用 Java 原生寫法,JSON 解析使用了 FASTJSON ,代碼簡單直接放上來了。

/**
 * <p>
 * 網絡請求操作工具類
 *
 * @author niujinpeng
 * @link https://github.com/niumoo
 */
public class HttpUtls {

    /**
     * 獲取 HTTP 連接
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static HttpURLConnection getHttpUrlConnection(String url) throws IOException {
        URL httpUrl = new URL(url);
        HttpURLConnection httpConnection = (HttpURLConnection)httpUrl.openConnection();
        httpConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36");
        return httpConnection;
    }

    /**
     * 請求指定 URL 的內容
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static String getHttpContent(String url) throws IOException {
        HttpURLConnection httpUrlConnection = getHttpUrlConnection(url);
        StringBuilder stringBuilder = new StringBuilder();
        // 獲得輸入流
        try (InputStream input = httpUrlConnection.getInputStream(); BufferedInputStream bis = new BufferedInputStream(
            input);) {
            byte[] buffer = new byte[1024];
            int len = -1;
            // 讀到文件末尾則返回-1
            while ((len = bis.read(buffer)) != -1) {
                stringBuilder.append(new String(buffer, 0, len));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpUrlConnection.disconnect();
        }
        return stringBuilder.toString();
    }

}

如果覺得 Java 原生網絡請求寫法繁瑣,也可以使用 OkHTTP 進行請求。請求到響應結果之后,使用 FASTJSON 解析響應的結果。

/**
 * @author niujinpeng
 * @link https://github.com/niumoo
 */
public class Wallpaper {

    // BING API
    private static String BING_API = "https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=1612409408851&pid=hp&FORM=BEHPTB&uhd=1&uhdwidth=3840&uhdheight=2160";

    private static String BING_URL = "https://cn.bing.com";

    public static void main(String[] args) throws IOException {
        String httpContent = HttpUtls.getHttpContent(BING_API);
        JSONObject jsonObject = JSON.parseObject(httpContent);
        JSONArray jsonArray = jsonObject.getJSONArray("images");

        // 圖片地址
        String url = BING_URL + (String)jsonArray.getJSONObject(0).get("url");
        url = url.substring(0, url.indexOf("&"));

        // 圖片時間
        String enddate = (String)jsonArray.getJSONObject(0).get("enddate");

        // 圖片版權
        String copyright = (String)jsonArray.getJSONObject(0).get("copyright");

        // 格式化為 MD 格式
        String text = String.format("%s | [%s](%s) ", enddate, copyright, url) + System.lineSeparator();
        System.out.println(text);
      
        // 寫入 MD 文件
        Path path = Paths.get("README.md");
        if (!Files.exists(path)) {
            Files.createFile(path);
        }
        List<String> allLines = Files.readAllLines(path);
        allLines.set(0, text);
        Files.write(path, "## Bing Wallpaper".getBytes());
        Files.write(path, System.lineSeparator().getBytes(), StandardOpenOption.APPEND);
        Files.write(path, allLines, StandardOpenOption.APPEND);
    }
}

運行之后就可以得到必應網站當天的壁紙信息。

20210226 | [掛在錦里街上的紅燈籠,中國成都 (© Philippe LEJEANVRE/Getty Images)](https://cn.bing.com/th?id=OHR.JinliStreet_ZH-CN3020276206_UHD.jpg) 

Github Actions

如果我們想要收集每天的必應壁紙,豈不是每天都要運行一次爬蟲程序?這顯然太麻煩了。如果有個定時任務每天自動執行一次,豈不妙哉?但是掛在服務器上還需要購買一台虛擬主機,實在得不償失。

這時機智的我突然想到何不利用 Github Actions 功能呢?Github Actions 可以執行多種常見環境的程序,而且可以定時觸發,免費好用,實在是妙,心中默默的也為微軟豎起了大拇指。

img

下面會簡單介紹一下 Github Actions 的使用,更多的關於 Github Actions 的概念和使用的場景就不介紹了,我們只要知道利用 Github Actions 功能,可以讓我們在指定的事件觸發(代碼提交事件或者定時或者其他)時,可以運行指定的程序就好了。

如果想了解更多的相關資料,可以直接參考 Github Actions 官方文檔,也可以參考其他的相關中文教程,鏈接這里已經放在文章末尾了。

Github Actions 體驗

在 Github 倉庫頁面的 Actions 頁簽下可以創建 Github Actions 配置,這里創建一個官方提供的簡單示例進行演示。

Github Actions

創建后可以得到一個官方編寫好的 Actions Demo,功能就是輸出幾個字符串。

GitHub Actions

簡單介紹一下圖中 Actions 配置文件中的的一些概念。

  1. on 指定此 Actions 的觸發機制,這里的 pushpull_request 說明在代碼提交和代碼合並時會觸發。
  2. jobs 代表一個任務,一個 Actions workflows 可以有多個 jobs 構成。
  3. runs-on 指定運行 Actions 的系統環境,這里是 ubuntu.
  4. steps 代表當前 jobs 任務的執行步驟。示例里先檢出了倉庫,然后echo 了幾個字符串。

保存提交這個文件到倉庫,因為配置里配置了觸發機制有 push,所以這時也會觸發這個任務。

Github Actions

Github Actions 定時抓取必應壁紙

已經簡單體驗了 Github Actions 的使用方式,還記得我們上面編寫了一個簡單的必應壁紙 Java 版爬蟲嗎?如果我們把爬蟲代碼提交到倉庫,然后使用 Github Actions 功能定時檢出倉庫運行 Java 代碼抓取壁紙,再寫入壁紙到倉庫,一套下來無服務器零成本豈不是很好?

先直接附上寫好的 Github 倉庫地址:https://github.com/niumoo/bing-wallpaper ,已經可以每天自動抓取當天必應壁紙。

下面是關於 Actions 內容的一些說明。

# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java CI with Maven
on:
  schedule:
    # 定時執行,Runs at 17:00 UTC every day
    - cron:  '0 17 * * *'
    
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set up JDK 1.8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: Build with Maven
      run: mvn -B package --file pom.xml
    - name: Run Java Application
      run: java -jar target/bing-wallpaper-jar-with-dependencies.jar
    - name: Commit files
      run: |
         git config --local user.email "your_github_email@126.com"
         git config --local user.name "your_github_name"
         git add README.md
         git commit -m "update readme.md"
    - name: Push changes
      uses:  ad-m/github-push-action@master
      with:
         github_token: ${{ secrets.MY_GIT_TOKEN }}
         branch: main

配置中定時在每天 UTC 時間 17 點運行一次,從 steps 可以看到執行步驟。

  1. 檢出代碼。
  2. 設置 Java 環境為 JDK 1.8.
  3. maven 編譯打包。
  4. 運行打包后的 Java 程序(程序中把獲取到的壁紙寫入到了 README.md 文件)。
  5. 提交文件到 Github 倉庫。

配置中最后還使用了一個參數 {{ secrets.MY_GIT_TOKEN }} ,這是一個用於識別是否有提交 Github權限的密文,這個密文可以在 Github 網站 -> 點擊頭像 -> Settings -> Developer settings -> Personal access tokens 這里創建,或者直接訪問 https://github.com/settings/tokens/new 創建,創建時勾選 repo 權限。保存后可以得到你的密文。

Github personal access tokens

復制這串密文,配置到自己創建 Actions 的倉庫。

Github Actions Secrets

至此,倉庫和配置都已經完成,每天自動抓取必應首頁壁紙寫入到 README.md 文件,下圖是抓取的效果。

bing-wallpaper

Github 倉庫地址:https://github.com/niumoo/bing-wallpaper

參考

[1] https://docs.github.com/en/actions/quickstart

[2] https://github.com/niumoo/bing-wallpaper

訂閱

<完>

Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。

點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。


文章持續更新,可以關注公眾號「 程序猿阿朗 」或訪問「未讀代碼博客 」。

回復【資料】有我准備的各系列知識點和必看書籍。

本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。

等你好久


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM