我是如何白嫖 Github 服务器自动抓取每日必应壁纸的?
分析必应壁纸 API
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
w=3840&h=2160
应该是指图片的宽和高,确实是这样,调整这两个参数可以返回不同分辨率的图片,如果没有这两个参数就可以返回超清原图。必应壁纸爬虫
请求必应壁纸 API。 JSON 解析出图片 URL。
/**
* <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();
}
}
/**
* @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 体验
on
指定此 Actions 的触发机制,这里的push
和pull_request
说明在代码提交和代码合并时会触发。jobs
代表一个任务,一个 Actions workflows 可以有多个jobs
构成。runs-on
指定运行 Actions 的系统环境,这里是ubuntu
.steps
代表当前jobs
任务的执行步骤。示例里先检出了仓库,然后echo
了几个字符串。
push
,所以这时也会触发这个任务。Github 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
steps
可以看到执行步骤。检出代码。 设置 Java 环境为 JDK 1.8. maven 编译打包。 运行打包后的 Java 程序(程序中把获取到的壁纸写入到了 README.md 文件)。 提交文件到 Github 仓库。
{{ secrets.MY_GIT_TOKEN }}
,这是一个用于识别是否有提交 Github权限的密文,这个密文可以在 Github 网站 -> 点击头像 -> Settings -> Developer settings -> Personal access tokens 这里创建,或者直接访问 https://github.com/settings/tokens/new 创建,创建时勾选 repo
权限。保存后可以得到你的密文。参考
[1] https://docs.github.com/en/actions/quickstart
[2] https://github.com/niumoo/bing-wallpaper
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️