百度站内搜索的坑

使用 Hugo 之后默认支持的是 Google 站内搜索,但是考虑到国内很多用户无法访问 Google 计划添加百度的站内搜索功能,但是遇到了一些坑,幸运的是最后还是巧妙的解决了问题。

生成百度站内搜索代码

进入官网:https://zn.baidu.com/cse/home/index?back=1&sid=16079160899252056172

新增一个站内搜索框:

百度站内搜索创建

创建过程中要注意了,这里有很多样式可选,当然你也可以不使用官方样式,而是使用你自己的搜索框样式:

创建自有样式搜索

如上图建议你点击 查看帮助 阅读一下内容,然后我们给博客的搜索框 <input> 添加 id="bdcsMain",我的搜索代码如下:

<div id="search-form-wrap">
    <form class="search-form">
        <input id="bdcsMain" class="search-form-input" placeholder="{{with .Site.Data.l10n.search.placeholder}}{{.}}{{end}}">
        <button type="submit" class="search-form-submit"></button>
    </form>
    <script type="text/javascript">
        (function(){
            document.write(unescape('%3Cdiv id="bdcs"%3E%3C/div%3E'));
            var bdcs = document.createElement('script');
            bdcs.type = 'text/javascript';
            bdcs.async = true;bdcs.src = '//znsv.baidu.com/customer_search/api/js?sid=xxxxxxxxx' + '&plate_url=' 
            + encodeURIComponent(window.location.href) + '&t=' + Math.ceil(new Date()/3600000);
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(bdcs, s);
        })();
    </script>
</div>

注意上面的 placeholder 是搜索框的默认提示语,还有 <script> 中的 sid 需要填写你自己的id.

接下来你在本地测试会发现没反应,那是因为有域名白名单,我们需要发布到正式域名才可以测试。

域名白名单设置

发布到正式环境后基本上就会成功,如果前面你的设置都正确的前提,如果有问题可以打开浏览器的控制台查看错误信息,但是不幸的是我的网站使用的是 HTTPS,而百度站内搜索链接均是 HTTP 的,所以你的浏览器控制台会报错。

HTTP不安全链接

尝试各种方式均无效,因为在百度的 js 文件中包含的 http 链接而不是 https,所以导致你的浏览器左上角会出现不安全标记,最后我还是换回到了 Google 站内搜索。

HTTP不安全链接

Google 站内搜索

官方创建链接:https://cse.google.com/cse/create/new

HTTP不安全链接

创建完成后会生成一段代码,复制以下代码,将其粘贴到您网站 <body> 部分的 <div> 元素中,此处既显示搜索框又显示搜索结果。

<script async src="https://cse.google.com/cse.js?cx=xxxxxxx:lnnnnnnn"></script>
<div class="gcse-search"></div>

当然更简单的方式是通过下面的连接自动生成 keywords site:url 进行搜索:

<div id="search-form-wrap">
    <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form">
        <input type="search" name="q" class="search-form-input" 
            placeholder="{{with .Site.Data.l10n.search.placeholder}}{{.}}{{end}}">
        <button type="submit" class="search-form-submit"></button>
        <input type="hidden" name="sitesearch" value="{{ .Site.BaseURL }}" />
    </form>
</div>

Google的链接搜索结构如下:

https://www.google.com/search?q=android&sitesearch=dp2px.com

触类旁通

根据上面 Google 的搜索方式我们猜测并实验后发现百度的链接搜索结果如下:

https://www.baidu.com/s?wd=android%20site:dp2px.com

根据上面的格式,我们使用 jQuery 拦截 submit 然后打开一个新界面并设置访问链接为上面的格式,从输入框获取关键字并拼接 {{ .Site.BaseURL }}即可。

<div id="search-form-wrap">
    <form action="//www.baidu.com/s" method="get" accept-charset="UTF-8" class="search-form">
        <input type="search" name="wd" class="search-form-input" 
                placeholder="{{with .Site.Data.l10n.search.placeholder}}{{.}}{{end}}">
        <button type="submit" class="search-form-submit"></button>
    </form>
    <script>
        $("#search-form-wrap form").submit(function(){
            var value = $("#search-form-wrap input").val();
            var tempwindow=window.open('_blank');
            var site = '{{ .Site.BaseURL }}';
            site = site.split("://")[1];
            tempwindow.location='//www.baidu.com/s?wd=' + value +  ' site:' + site;
            return false;
        });
    </script>
</div>

注意上面的 {{ .Site.BaseURL }} 你也可以直接在链接上拼接成你的网站域名 site:dp2px.com

扩展

既然我们已经知道了 Google 搜索引擎和百度搜索引擎的搜索链接,而且我们想优先选择 Google 搜索,只有在我们不具备访问条件的时候才自动切换到百度,接下来我们就是用 ajax 来判断是否可以访问 Google 然后进行自动选择。

<script>
    var isSearching = false;
    $("#search-form-wrap form").submit(function(){
        if(isSearching) return;
        isSearching = true;
        $.ajax({
            type: "POST",
            timeout: 2000,
            url: "https://www.google.com",
            success: function(data, textStatus, jqXHR){
                isSearching = false;
                var value = $("#search-form-wrap input").val();
                var tempwindow=window.open('_blank');
                tempwindow.location='//google.com/search?q=' + value +  '&sitesearch={{ .Site.BaseURL }}';
            },
            error: function(jqXHR, textStatus, errorThrown){
                isSearching = false;
                var value = $("#search-form-wrap input").val();
                var tempwindow=window.open('_blank');
                var site = '{{ .Site.BaseURL }}';
                site = site.split("://")[1];
                tempwindow.location='//www.baidu.com/s?wd=' + value +  ' site:' + site;
            }
        });
        return false;
    });
</script>

把上面代码再简单优化一下,并添加一个加载动画吧。

<script>
    var isSearching = false;
    $("#search-form-wrap form").submit(function(){
        if(isSearching) return false; //防止重复请求
        $.ajax({
            type: "POST",
            timeout: 2000,
            url: "https://www.google.com",
            beforeSend: function(jqXHR){
                isSearching = true;
                $("#search-form-loadding").show(); //显示加载动画
            },
            complete: function(jqXHR, textStatus){
                isSearching = false;
                $("#search-form-loadding").hide(); //关闭加载动画
                var value = $("#search-form-wrap input").val();
                var tempwindow=window.open('_blank');
                if(jqXHR.readyState == 200){
                    tempwindow.location='//google.com/search?q=' + value +  '&sitesearch={{ .Site.BaseURL }}';
                }else{
                    var site = '{{ .Site.BaseURL }}';
                    site = site.split("://")[1];
                    tempwindow.location='//www.baidu.com/s?wd=' + value +  ' site:' + site;
                }
            }
        });
        return false;
    });
</script>

目前这应该是目前最简便的 Hugo 博客引入站内搜索的方式了,如果你有什么更好的方式可以告诉我。