1. 前言
最近探索搜索引擎收录功能,发现现阶段Halo的插件站点收录推送
插件并未实现IndexNow推送功能,因此决定自行实现。
此处,需要确定完成如下配置:
1.1 IndexNow配置
上图中蓝色遮盖内容,是Bing的IndexNow功能生成的Api Key,此处我已经完成相应的OpenResty配置。
1.2 SiteMap.xml配置
当前Halo博客已经启用Sitemap
插件,访问https://www.2tuan.site/sitemap.xml即可获取到本站点的URL列表,具体如下图:
2 编写推送应用
2.1 sitemap.xml抽象实体类
URL实体类:
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "url")
public class Url {
@JacksonXmlProperty(localName = "loc")
private String loc;
}
URLSet实体类:
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JacksonXmlRootElement(localName = "urlset")
public class UrlSet {
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "url")
private List<Url> urls;
}
以上实体类属于嵌套关系。
2.2 获取sitemap.xml并获取URL列表
private void pushIndexImpl() {
getSiteMapXml().ifPresentOrElse(
siteMapXml -> {
XmlMapper xmlMapper = new XmlMapper();
try {
var urlSet = xmlMapper.readValue(siteMapXml, UrlSet.class);
urlSet.getUrls().forEach(url -> log.info("推送链接:{}", url.getLoc()));
pushIndexToBing(urlSet.getUrls());
} catch (Exception e) {
log.error("解析网站地图失败", e);
}
},
() -> log.error("获取网站地图失败"));
}
private Optional<String> getSiteMapXml() {
var request = new Request.Builder()
.url("https://www.2tuan.site/sitemap.xml")
.build();
try (var response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
if (response.body() != null) {
return response.body().string().describeConstable();
}
}
} catch (Exception e) {
log.error("获取网站地图失败", e);
}
return Optional.empty();
}
此处,使用OkHttpClient构建sitemap.xml查询请求,并基于Jackson的XmlMapper进行解析,得到URL列表。
<!-- XmlMapper需要引入如下依赖 --> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> </dependency>
2.3 推送URL列表至IndexNow端点
IndexNow接口实体类:
@Data
@NoArgsConstructor
public class IndexNow {
private String host = "www.2tuan.site";
private String key = "xxxxxx";
private String keyLocation = "https://www.2tuan.site/xxxxxx.txt";
private List<String> urlList;
public IndexNow(List<Url> urlList) {
this.urlList = new ArrayList<>();
urlList.forEach(url -> this.urlList.add(url.getLoc()));
}
}
推送相关代码如下:
private void pushIndexToBing(List<Url> urls) {
try {
String content = objectMapper.writeValueAsString(new IndexNow(urls));
var requestBody =
RequestBody.create(content, MediaType.parse("application/json; charset=utf-8"));
var request = new Request.Builder()
.url("https://api.indexnow.org/IndexNow")
.post(requestBody)
.build();
try (var response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
log.info("推送索引成功,推送内容:{}", content);
} else {
if (response.body() == null) {
log.error("推送索引失败,响应码:{}", response.code());
} else {
log.error("推送索引失败,响应码:{},响应内容:{}", response.code(),
response.body().string());
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
3. 编写启动脚本
脚本中关键步骤均已给出具体注释,请参考后自行更新。
#!/bin/bash
# 旧应用程序的名称
old_app_name="blog-index-pusher"
# 启动当前目录下的应用程序
new_app_path="blog-index-pusher-0.0.1.jar"
# 获取旧应用程序的进程 ID
old_app_pid=$(pgrep -f $old_app_name)
# 如果找到了旧应用程序的进程,结束它
if [ -n "$old_app_pid" ]; then
# 输出提示信息(包括原应用进程ID)
echo "Stopping old application with PID $old_app_pid..."
kill -15 "$old_app_pid"
sleep 5
fi
# 检查应用程序是否已经结束
old_app_pid=$(pgrep -f $old_app_name)
if [ -n "$old_app_pid" ]; then
# 如果应用程序没有结束,强制结束
echo "Forcing old application to stop..."
kill -9 "$old_app_pid"
sleep 5
fi
# 启动新应用程序,并且忽略所有输出(有日志)
echo "Starting new application..."
nohup java -jar $new_app_path > /dev/null 2>&1 &