在静态页中使用必应搜索

博客搜索框跳转搜索结果,搜索引擎从 BD 改 必应。很琐碎,且没有什么技术含量。纯粹因为平时不写前端,记一下,避免以后忘了还得查这些琐碎的内容。

原版

博客是 github pages,生成器是 hexo,模板 landscape-plus。自带的搜索框如下:

1
2
3
4
5
6
7
8
<form action="http://www.baidu.com/baidu" method="get" accept-charset="utf-8" class="search-form">
<input type="search" name="word" maxlength="20" class="search-form-input" placeholder="Search">
<input type="submit" value="" class="search-form-submit">
<input name=tn type=hidden value="bds">
<input name=cl type=hidden value="3">
<input name=ct type=hidden value="2097152">
<input type="hidden" name="si" value="<%- config.url.replace(/^https?:\/\//, '') %>">
</form>

<%- config.url.replace(/^https?:\/\//, '') %> 是 hexo 的模板代码,实际页面会替换成 jaycechant.info 。这样写是为了把域名变成变量,避免以后如果改域名还得一个一个地方修改。

就一个 form,action 设置为 get baidu 搜索页,下面的 input 都会按 name 追加在 query string。通过这种方式,在提交时跳转到一个搜索结果。

例如,搜索博客的关于 Golang 的内容:http://www.baidu.com/baidu?word=Golang&tn=bds&cl=3&ct=2097152&si=jaycechant.info

显示:很抱歉,没有找到与“Golang”相关的网页。

很长一段时间,都没有注意到它。早期文章少,也用不上搜索。

直到有一天,发现博客还有引用 http 资源,排查的时候,才留意到这个搜索框。因为众所周知的原因,不想用 BD。何况它也没收录我的博客。

更换

失败

首选 Google。不过这不光是给我用的,读者也可能用,只能选方便访问的 Bing。

同样在 Bing 搜上面的内容,拿到对应的 URL :https://bing.com/search?q=site%3ajaycechant.info+Golang

这回有结果了。

不过 site 参数跟搜索关键词混在一起,需要想办法自动添加。

1
2
3
4
5
6
<form action="https://global.bing.com/search" method="get" accept-charset="utf-8" class="search-form">
<input type="search" name="q" maxlength="20" class="search-form-input" placeholder="Search">
<input type="submit" value="" class="search-form-submit">
<input name="si" type="hidden" value="<%- config.url.replace(/^https?:\/\//, '') %>">
<input name="ensearch" type="hidden" value="1">
</form>

这样是不行的。Bing 不识别 si 。类似的, site 也不识别。搜索,查文档,测试,Bing 貌似没有给来源站点提供独立的 query 参数。

也试过放两个 q 参数,后面那个 <input name="q" type="hidden" value="site:jaycechant.info"> ,也不行,同名的两个 query 参数,只有最后一个会起效,相当于覆盖效果。

方案一

然后发现自己陷入思维定势。被从原来的搜索框改限定了思路。

用 js 拼接一下 q 的 value 就可以了。

1
2
3
4
5
<form action="https://global.bing.com/search" accept-charset="utf-8" class="search-form" onsubmit="document.getElementById('searchtext').value+=' <%- config.url.replace(/^https?:\/\//, '') %>';return true;">
<input id="searchtext" type="search" name="q" maxlength="20" class="search-form-input" placeholder="Search">
<input type="submit" value="" class="search-form-submit">
<input name="ensearch" type="hidden" value="1">
</form>

这样已经足够简单了,不过表单一提交就会跳转到搜索页,能不能留住读者,不要跳出博客?这个简单,可以用 target="_blank" 解决。

不过还有一个问题:关键词被修改了,如果连续搜索,关键词会不断添加 site。要么难看,干扰真正的关键词;要么要读者手动删掉。

方案二

还是思维定势:这个 form 一定要提交吗?

直接 onclick="window.open('')" 不行吗?

回车不起效?拦截 keycode 就好了。

1
2
3
4
5
<form action="" accept-charset="utf-8" class="search-form">
<input id="searchtext" type="search" name="q" maxlength="20" class="search-form-input" placeholder="Search" onkeypress="if(event.keyCode==13){document.getElementById('searchsub').click();return false;}">
<input id="searchsub" type="submit" value="" class="search-form-submit" onclick="window.open('https://global.bing.com/search?q=site:<%- config.url.replace(/^https?:\/\//, '') %> '+document.getElementById('searchtext').value, '_blank')">
<input name="ensearch" type="hidden" value="1">
</form>

效果还满意,不多折腾,收工。

其他方案

除此以外,还有一些备选方案,因为时间关系,没有折腾,先 Mark。

第三方站内搜索

调用第三方的服务,如 SwiftypealgoliaBonsaiExpertRec阿里云开放搜索 等。

简单说,注册帐号,提供站点地址,配置各种选项,他们就帮忙索引。然后通过 API 也好,嵌入 js 也好,提供搜索服务。

本质上跟传统搜索引擎没有太大区别,只是既然你注册了,就一定会收录你的站点,以及可以配置。

相应的,多数收费,最多提供有条件的免费(限时、限额)。

基于 js 的站内搜索

静态博客如果不想依赖其它服务,那么唯一可以提供动态能力的,就只有 js 了。仍然是静态页,没有 hosted server,就把跑脚本的负担,转移到浏览器。

选项有 lunr.js,基于 lunr.js 的 elasticlunr.jsFuse.js 等。

简单说,静态站点生成时,就把索引一起生成。搜索时,脚本在用户端运行,读取索引进行搜索。

看着很美好,但是有一些因素制约了使用:

  • 所有索引数据加载到用户端,并在浏览器运行,对于网速和性能有一定要求,否则影响用户体验。
  • 同样的,索引数据不能太大,因此不适合大站点使用;小站点也不方便做全文索引,大多只索引 title 和 tag。
  • 需要索引,也就需要分词,很多 lib 对中文支持不好,需要额外增加插件或者踩坑。

纯记录,暂时没有动力折腾这两种方案。


知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议
本文为本人原创,采用知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议进行许可。
本作品可自由复制、传播及基于本作品进行演绎创作。如有以上需要,请留言告知,在文章开头明显位置加上署名(Jayce Chant)、原链接及许可协议信息,并明确指出修改(如有),不得用于商业用途。谢谢合作。
请点击查看协议的中文摘要。