写在前面
偶然在逛 Bing 的 Webmasters 的时候,发现多了个 IndexNow 原先一直用的 Hexo-SEO-AutoPush 但是有新东西了,和乐特子提了一下,他让我 PR,可惜 JavaScript 不太熟,索性自己用 JAVA 写了个,也顺便学习了 XML 解析器和 XPath 表达式
项目地址:sudojia/hexo-auto-submit-urls
开发思路
- 获取 RSS 地址
- 进行解析 RSS 并使用 XPath 表达式提取其中的 ID 标签
/** * 从XML内容中提取id值。 * 首先解析XML内容,然后使用XPath表达式定位到id元素的文本内容,并将这些内容收集到一个列表中。 * * @param xmlContent 要解析的XML内容,作为字符串提供。 * @param ids 用于收集提取到的id值的列表。 * @throws Exception 如果解析XML或执行XPath表达式时发生错误,则抛出异常。 */ private static void extractIds(String xmlContent, List<String> ids) throws Exception { // 创建一个文档工厂实例,用于构建XML文档解析器 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 使用文档工厂创建一个文档构建器 DocumentBuilder db = dbf.newDocumentBuilder(); // 将XML内容解析为DOM文档 Document doc = db.parse(new ByteArrayInputStream(xmlContent.getBytes(StandardCharsets.UTF_8))); // 创建XPath工厂,用于生成XPath实例 XPathFactory xPathFactory = XPathFactory.newInstance(); // 创建XPath实例,用于评估XPath表达式 XPath xpath = xPathFactory.newXPath(); // 编译XPath表达式,用于定位id元素的文本内容 XPathExpression expr = xpath.compile("//feed/entry/id/text()"); // 执行XPath表达式并获取匹配的节点列表 NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); // 遍历节点列表,将id文本添加到收集列表中 for (int i = 0; i < nodeList.getLength(); i++) { ids.add(nodeList.item(i).getNodeValue()); } } - 最后将这些 ID 循环写入 urls.txt 文件
/** * 将一串ID写入到指定的文本文件中。 * 每个ID占一行。 * * @param ids 包含需要写入文件的所有ID的列表。 * @throws IOException 在写入文件过程中发生IO异常。 */ private static void writeIdsToFile(List<String> ids) throws IOException { // 使用BufferedWriter来提高文件写入性能,通过FileWriter指定写入的文件路径 try (BufferedWriter writer = new BufferedWriter(new FileWriter(TXT_FILE_PATH))) { // 遍历ids列表,将每个ID写入文件,如果ID不是最后一个,则在后面添加换行符 for (int i = 0; i < ids.size(); i++) { // 写入当前ID writer.write(ids.get(i)); if (i < ids.size() - 1) { // 如果当前ID不是最后一个,则写入换行符 writer.newLine(); } } } } - 使用并发批量提交 urls.txt 的文本内容到不同的搜索引擎
/** * 向多个搜索引擎提交URLs。 * * @param host 主机地址 * @param siteUrl 网站的URL * @param indexNowkey IndexNow的密钥 * @param keyLocation 密钥存储位置 * @param bingApiKey Bing搜索引擎的API密钥 * @param baiduApiKey 百度搜索引擎的API密钥 * @param googleKey Google搜索引擎的json文件内容 * @param indexNowCount 向IndexNow提交的URL数量 * @param bingCount 向Bing提交的URL数量 * @param baiDuCount 向百度提交的URL数量 */ private static void submitUrls(String host, String siteUrl, String indexNowkey, String keyLocation, String bingApiKey, String baiduApiKey, String googleKey, Integer indexNowCount, Integer bingCount, Integer baiDuCount) { List<String> urlList; try { // 从文件中读取 urls 列表 urlList = ReptileRssTools.readUrlsFromFile(); if (urlList.isEmpty()) { // 如果URL列表为空或读取失败, 取消提交 LOGGER.log(Level.SEVERE, "URL 列表为空或读取 rss 失败, 取消提交!"); return; } } catch (Exception e) { LOGGER.log(Level.SEVERE, "读取 URL 列表时发生异常" + e.getMessage()); return; } // 创建一个固定大小为 5 的线程池,用于并发提交URL到不同的搜索引擎 ExecutorService executorService = Executors.newFixedThreadPool(5); // 向IndexNow提交URL任务 executorService.submit(() -> { try { AutoSubmitUrlServiceImpl.pushIndexNowUrl(urlList, host, indexNowkey, keyLocation, indexNowCount); } catch (Exception e) { LOGGER.log(Level.SEVERE, "提交 URL 到 IndexNow 时发生异常", e.getMessage()); } }); // 向Bing提交URL任务 executorService.submit(() -> { try { AutoSubmitUrlServiceImpl.pushBingUrl(urlList, siteUrl, bingApiKey, bingCount); } catch (Exception e) { LOGGER.log(Level.SEVERE, "提交 URL 到 Bing 时发生异常", e.getMessage()); } }); // 向百度提交URL任务 executorService.submit(() -> { try { AutoSubmitUrlServiceImpl.pushBaiduUrl(urlList, siteUrl, baiduApiKey, baiDuCount); } catch (Exception e) { LOGGER.log(Level.SEVERE, "提交 URL 到 Baidu 时发生异常", e.getMessage()); } }); // 向Google提交URL任务 executorService.submit(() -> { try { AutoSubmitUrlServiceImpl.pushGoogleUrl(urlList, googleKey); } catch (Exception e) { LOGGER.log(Level.SEVERE, "提交 URL 到 Google 时发生异常", e.getMessage()); } }); // 关闭线程池,并等待所有任务完成 executorService.shutdown(); try { // 长时间等待所有任务完成,以确保所有提交任务执行完毕 executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { // 如果在等待线程池关闭时线程被中断时,尝试恢复中断状态 LOGGER.log(Level.SEVERE, "线程池等待终止时发生异常", e.getMessage()); Thread.currentThread().interrupt(); } }
如何使用
-
本项目是利用
hexo-generator-feed生成的 RSS 进行解析并获取文章列表,所以需要你在 Hexo 安装该插件npm install hexo-generator-feed --save然后在博客的配置文件里添加如下配置
feed: enable: true type: atom path: atom.xml limit: 0 hub: content: true content_limit: content_limit_delim: ' ' order_by: -date icon: 图标.icon # 修改你的图标 autodiscovery: true template:详情见插件地址:hexojs/hexo-generator-feed
-
【Fork】本项目并在仓库的
settings -> Secrets and variables -> Actions -> New repository secret添加环境变量- 详情见【参数说明】
-
最后在 Actions 运行 Workflows 文件
参数说明
| Secrets | Value 说明 |
|---|---|
| RSS_URL | rss 地址,eg:https://example.org/atom.xml |
| INDEX_NOW_KEY | www.bing.com/indexnow/ge… 获取 KEY 并把文件下载到本地,放在 Hexo 根目录的 source 下 eg: 6b0e36ed24d24c68a6f3415c41ee849a |
| BING_KEY | www.bing.com/webmasters/… 设置 -> API 访问 -> 查看 API 密钥 |
| BAIDU_KEY | ziyuan.baidu.com/linksubmit/… 只要 token 的值 |
| GOOGLE_KEY | JSON 内容,到 json.cn 压缩代码 |
| BOT_TOKEN | 通过 @BotFather 获取机器人 token |
| CHAT_ID | 和它对话获取 chat_id @userinfobot |
提交数量:
因本项目是获取你的 RSS 地址,所以你 RSS 有多少条文章链接,就提交多少条,如需要设置提交数量可在 KEY 的后面加个 , 隔开数量
注意是英文的逗号,另 GOOGLE_KEY 没有写提交数量,默认就是你的 RSS 文章链接数量
eg: hCvGPEqkx7L5hJur,100
特别说明:
-
INDEX_NOW_KEY: Secrets 变量里不仅需要填入 KEY,还需要你把它那个文件下载并放入到网站的根目录,可以参考官方的请求示例:
keyLocationPOST /IndexNow HTTP/1.1 Content-Type: application/json; charset=utf-8 Host: api.indexnow.org { "host": "www.example.org", "key": "960ca71a21c141f7a4deb8edcb256bf4", "keyLocation": "https://www.example.org/960ca71a21c141f7a4deb8edcb256bf4.txt", "urlList": [ "https://www.example.org/url1", "https://www.example.org/folder/url2", "https://www.example.org/url3" ] } -
BAIDU_KEY: 百度提交的好像大部分站长都是 10 条,所以本项目百度提交默认为 10 条,有需求的可以在 token 后加个
,提交的数量hCvGPEqkx7L5hJur,100 -
GOOGLE_KEY: 前提你需要创建项目并启用
Web Search Indexing API,最后创建密钥时把JSON文件下载到本地,前置操作可以参考【如何使用google index api来自动提交url】挺详细的。然后打开【json.cn】压缩 JSON 代码,并填入压缩后的代码
结语
该收录的自然会收录,瞧不上的自然瞧不上
文章作者: GarveyZhong
文章链接: blog.imzjw.cn/posts/3ed40…
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小嘉的部落格!