2团
Published on 2024-08-15 / 13 Visits
0
0

Bing搜索引擎IndexNow推送功能实现

1. 前言

最近探索搜索引擎收录功能,发现现阶段Halo的插件站点收录推送插件并未实现IndexNow推送功能,因此决定自行实现。

此处,需要确定完成如下配置:

1.1 IndexNow配置

image.png

上图中蓝色遮盖内容,是Bing的IndexNow功能生成的Api Key,此处我已经完成相应的OpenResty配置。

1.2 SiteMap.xml配置

当前Halo博客已经启用Sitemap插件,访问https://www.2tuan.site/sitemap.xml即可获取到本站点的URL列表,具体如下图:

image-cljh.png

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 &

4. 推送效果

image-lysp.png


Comment