乐趣区

关于java:如何使用-Github-Actions-自动抓取每日必应壁纸

如何白嫖 Github 服务器主动抓取必应搜寻的每日壁纸呢?

如果你拜访过必应搜寻网站,那么你肯定会被搜寻页面的壁纸吸引,必应搜寻的壁纸每日不同,主动更换,非常精美。这篇文章会介绍如何一步步剖析出必应搜寻壁纸 API,如何联合 Github Actions主动抓取每日必应壁纸到 Github 仓库。

元宵节当天具备中国元素的必应搜寻。


<!– more –>
平时一天的必应搜寻。

剖析必应壁纸 API

既然是网站上的背景,又是每天更换,很大概率是通过某个 API 申请返回壁纸信息的,事实真是如此吗?间接关上浏览器 network 控制台监控网络申请信息。

筛选 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 能够执行多种常见环境的程序,而且能够定时触发,收费好用,切实是妙,心中默默的也为微软竖起了大拇指。

上面会简略介绍一下 Github Actions 的应用,更多的对于 Github Actions 的概念和应用的场景就不介绍了,咱们只有晓得利用 Github Actions 性能,能够让咱们在指定的 事件触发 (代码提交事件或者 定时 或者其余)时,能够运行指定的程序就好了。

如果想理解更多的相干材料,能够间接参考 Github Actions 官网文档,也能够参考其余的相干中文教程,链接这里曾经放在文章开端了。

Github Actions 体验

在 Github 仓库页面的 Actions 页签下能够创立 Github Actions 配置,这里创立一个官网提供的简略示例进行演示。

创立后能够失去一个官网编写好的 Actions Demo,性能就是输入几个字符串。

简略介绍一下图中 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 的应用形式,还记得咱们下面编写了一个简略的必应壁纸 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/t… 创立,创立时勾选 repo 权限。保留后能够失去你的密文。

复制这串密文,配置到本人创立 Actions 的仓库。

至此,仓库和配置都曾经实现,每天主动抓取必应首页壁纸写入到 README.md 文件,下图是抓取的成果。

Github 仓库地址:https://github.com/niumoo/bing-wallpaper。

参考

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

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

订阅

文章曾经收录到 github.com/niumoo/javaNotes

能够关注未读代码博客或者微信搜寻「未读代码」。

文章会在博客和公众号同步更新。

退出移动版