My Hexo Plugin - Submit Pages To Search Engine (一)

前言

该系列文章用于记录自己写的第一个 hexo plugin 的步骤;名字叫做 hexo-submit-to-search-engines

申明:本文为作者的原创作品,转载需注明出处;

需求

想写这么一个插件,其作用是用来自动提交静态链接给搜索引擎收录;在调研百度搜索引擎的时候,发现,虽然可以简单的给一个根域名地址让百度搜索引擎收录,但是发现这样做,很难实际上奏效,要么要等上非常长的时间,要么百度搜索引擎就只会收录你的首页上的信息;所以它建议是按照一定的标准格式,依次提交每一个静态网页的连接地址给百度搜索引擎,这样是最有效的,一般 24 小时以内,新的静态页面就被收录了;

其它搜索引擎,比如 Google 和 Bing 还没有实际调研过,但想想,应该都差不多;

那么问题来了,要知道 hexo 只是一个静态网站,它如何自动的去提交所有的静态链接地址给百度收录呢?难道写一个 Java/Python/Shell 小程序,去依次遍历 hexo public 文件夹下的路径,然后生成所有的 urls,最后做一次 Http Post? 这样做,的确可行,但是方式太笨重;能不能有一种安安静静的方式,在每次执行hexo generate命令既生成静态页面的时候,自动的将静态链接发送给百度搜索引擎收录呢?答案是可行的,只是,要写 Hexo Plugins,这也就是写该系列文章的初衷了;

调研准备工作

百度收录的方式

直接提交入口

看似百度提供了这样一个第三方公共提交的窗口 http://www.baidu.com/search/url_submit.html; 可以任意的提交让百度去收录的地址,但是,因为无法验证该网站是否属于你本人所有,其实是很难让百度去收录的;所以要做的是,注册成为百度站长平台的用户,然后验证该网站是否归属本人所有(顺带可以添加站内搜索),具体步骤参考添加百度站内搜索;当验证了该网站是本人所有以后,可以通过百度站长平台内部的通道使用主动和自动提交方式进行网站静态页面链接的提交,让百度第一时间收录;

自动提交方式

这部分内容可以参考让百度收录网站;登录你的站长平台 http://zhanzhang.baidu.com/linksubmit/index?site=http://www.shangyang.me/ 以后,进入网页抓取 -> 链接提交,可以看到,自动提交有三种方式,主动推送(实时),自动推送,以及 sitemap;自动推送就是在你的页面上添加百度搜索的 javascript 脚本,当页面每次被用户点击的时候,会将链接推送给百度;这里,由于自己的博客还没有被百度收录过,访问量不大,所以想让百度能够尽快的进行收录,最快捷的方式就是采用主动推送(实时)的方式;给一张相关截图如下,

归纳起来,就是要向 data.zz.baidu.com 发送一个包含所有静态链接的 post 请求;

hexo plugins API

hexo

hexo这个是最重要的元素,里面包含了logEnvEventsLocals等等… 给张 debug 截图

hexo log

使用 hexo.log.info(string) 方法来打印 log;(除了 info 以外,还有 debug、fatal 等)

hexo Env

里面包含了所有 hexo 环境相关的参数;比如,下面是执行命令hexo server --draft返回的信息;可以看到 args 中的 draft 参数值为 true;

1
2
3
4
5
6
7
8
env: 
{ args: { _: [], draft: true },
debug: false,
safe: false,
silent: false,
env: 'development',
version: '3.2.2',
init: true },

如果是执行hexo server,可以看到 args 为空

1
2
3
4
5
6
7
8
 env: 
{ args: { _: [] },
debug: false,
safe: false,
silent: false,
env: 'development',
version: '3.2.2',
init: true },

hexo Events

https://hexo.io/api/events.html 定义了大量的时间的回调接口,这里需要关注的有,

  • generateBefore
    在生成静态页面之前
  • generateAfter
    在生成静态页面之后

为了满足我当前的需求,我需要使用到的就是generateAfter这个 Event

hexo Locals

这个参数相当的重要,官网上给的解释过于简单,

Local variables are used for template rendering, which is the site variable in templates.

用来渲染模板的本地变量,同样也是模板里面的 site variable;包含哪些 variables 呢?

Variable Description
posts All posts
pages All pages
categories All categories
tags All tags

它到底有多重要呢?更准确的描述,这个其实有点类似于SpringContext,集合了所有当前环境的所有变量,参数,对象;有多重要,这就不言而喻了~;基本上,每一个 hexo 的插件都会使用到它;

开始我的第一个 Hexo Plugins

开发环境搭建

前言

写在最前面,作者目前为止,还没有找到关于 hexo 插件开发的集成环境或IDE之类的,所以,基本上,没办法通过 IDE 的方式进行调试工作 (这方面有经验的读者可以给作者留言,万分感激!),而现在作者进行调试的方式只是通过 console.log 这样的方式;

构建你的 plugin

https://hexo.io/docs/plugins.html 给出了较为详细的步骤,这里呢,还是打算一步一步的更为详细的来阐述一下,

  1. 首先在 node_modules 目录下创建自己的插件文件夹 hexo-submit-to-search-engine
    这一步要注意的是,根据 hexo 的规范,所有 hexo 相关的插件的文件夹命名都应该以 hexo 开头;

  2. 生成插件的骨架
    这里,我通过 npm 的命令直接生成项目的骨架;对 npm 不太熟悉的朋友可以参考作者的另外一篇文章 NPM

    1
    2
    $ cd node_modules/hexo-submit-to-search-engines
    $ npm init

    生成好了以后,会在根目录下生成

    1
    2
    $ ls
    index.js package.json

    index.js 也就是 hexo 调用的入口文件了;

  3. 在 hexo 根 package.json 文件中添加 hexo-submit-to-search-engines 信息

    1
    "hexo-submit-to-search-engine": "^0.0.1"

这样,hexo 在每次启动的时候,就会开始调用插件 hexo-submit-to-search-engines 中的 index.js 了;好了,下面开始我们的第一个 hexo plugin 程序的撰写;

我的第一个 plugin 程序

一些功能调试

index.js 进行如下代码的调试,

  1. 添加 generateAfter 回调事件;

    1
    2
    3
    hexo.on('generateAfter', function(){
    console.log("hello world");
    })

    在命令行执行 hexo g,

    1
    2
    $ hexo g
    hello world
  2. hexo.locals 的属性值

    1
    2
    3
    hexo.on('generateAfter', function(){
    console.log( hexo.locals.get("posts"));
    })

    执行 hexo generate,会输出所有相关的 posts 的信息,从这里面,可以看到一个关键的属性值 _canonical_path_,是什么,一个类似于这样的 2017/05/21/encrypt-rsa-pkcs/index.html 的字符串,还差什么?那就是你的域名了,看来 hexo 是非常贴心的把 url 的相对路径已经给你保存下来了;后续要做的就是,遍历 posts 中的每一个 post 元素,取得 _canonical_path_ 属性值,然后拼接出需要提交给搜索引擎的 url,然后批量提交;

所以,相关的准备工作差不多了,下面就开始动工了…

开发

开发之前,要注意的是,百度搜索引擎不推荐每次 post 一个链接,你要做的是,将所有需要 post 的 urls 放到一起,然后执行一次 post 请求;

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* global hexo */

'use strict';

var http = require('http');

/*
* reference with http://zhanzhang.baidu.com/linksubmit/index
*/
hexo.on('generateAfter', function(){

var domain = "http://www.shangyang.me"; // hard coded there

var c = ""; // the post content

/*
* 下面这段代码会输出所需要的相对路径;签名跟上博客的域名即可访问该网址
*
* 2016/12/20/docker-basics/index.html
* 2016/12/22/docker-cgroups/index.html
* 2016/12/18/docker-aufs/index.html
* 2016/12/20/docker-image/index.html
* ...
*/
hexo.locals.get("posts").each(function(post){

//console.log(post.canonical_path);

var url = domain+"/"+post.canonical_path;

//console.log(url);

c = c += ( url + "\r\n" );

})

console.log( c +"\r\n" + Buffer.byteLength(c) );

// start to post the data to baidu search engine

var post_options = {
host: 'data.zz.baidu.com',
port: '80',
path: '/urls?site=www.shangyang.me&token=yourtoken',
method: 'POST',
headers: {
'User-Agent': 'curl/7.12.1',
'Content-Type': 'text/plain ',
'Content-Length': Buffer.byteLength(c)
}
};

var post_req = http.request(post_options, function(res) {
//res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response from post pages into baidu search engine:' + chunk);
});
});

post_req.write(c);
post_req.end();

});

上面实现的就是一个原始代码的逻辑,大部分需要配置的内容全部是 hard coded 的,不过,已经能够适用于百度搜索引擎了;遗留的问题有,将来需要重构的地方有,

  1. 每次只提交增量信息,也就是新的 url 链接
  2. 将所有 hard code 的地方改为动态配置的方式
  3. 新增 Google、Bing 等搜索引擎的自动提交逻辑;

执行验证

执行,执行过程中,会调用插件 submit-to-search-engines,发送 post 请求;

1
$ hexo g

post 请求的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /urls?site=www.shangyang.me&token=yourtoken&type=original HTTP/1.1
User-Agent: curl/7.12.1
Content-Type: text/plain
Content-Length: 4785
Host: data.zz.baidu.com
Connection: close

http://www.shangyang.me/2016/12/18/docker-aufs/index.html
http://www.shangyang.me/2016/12/22/docker-cgroups/index.html
http://www.shangyang.me/2016/12/20/docker-basics/index.html
http://www.shangyang.me/2016/12/20/docker-image/index.html
http://www.shangyang.me/2017/01/08/docker-namespace-network/index.html
...

百度搜索反馈的信息

1
2
3
4
5
6
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 72
Connection: close

{"remain":4999876,"success":62,"remain_original":0,"success_original":0}

  1. remain
    表示当日,你还可以提交的 url 链接的数目;

  2. success
    成功了多少链接的提交;

TODO

  1. 重构代码
    让该 plugins 更 Generic,不但可以支持百度搜索引擎,而且要能支持 Google、Bing 等..

  2. 每次值提交新的链接
    百度搜索引擎要求最好是,每次能够只是提交网站新的静态链接,现在的做法是,每次提交所有的连接,毕竟连接不多;但是为了满足搜索引擎的癖好,后续考虑在本地做一个 cache,保存每次提交后的连接,然后比对以后,将新增的链接提交;

  3. 实现 Google、Bing 等搜索引擎的接入;

Reference

How to Submit Your Site to Search Engines: https://www.smartz.com/web-marketing/search-engine-optimization/submit-site-to-search-engines/