善用Referer變量 -- 針對搜索引擎來源用戶的提示

  1. 前言
  2. 實現效果
  3. 實現思路
  4. Java編碼實現
  5. 其他 

1 前言:

注意到不少站點都有這個功能(包括javaeye和pconline)。

就是從百度/谷歌等搜索頁面點過來的用戶可以看見頁面下方有搜索幫助提示,如圖:

ScreenShot012 

前一陣子給CTBA也加上了相關功能, 這裏大致說說實現方法。 

2 實現效果:

百度搜索”扯談 新聞風”

ScreenShot025

點擊進入CTBA的網站, 頁面底部顯示提示

 

3 實現思路:

參考了這篇文章, 利用請求的referer頭. 如果乃還不知道referer是什麼的話, 點這裏

  • 從referer頭中取得來源頁面的地址
  • 解析出查詢關鍵詞
  • 全文檢索得出結果

首先必須分析referer, 知道url中哪部分是關鍵字。例如在baidu輸入關鍵字"扯談社",在搜索結果中訪問你的網站,那麼來源的url就是:http://www.baidu.com/s?wd=%B3%B6%CC%B8%C9%E7上面的url中,wd=%B3%B6%CC%B8%C9%E7就是關鍵字部分,其中%B3%B6%CC%B8%C9%E7是"扯談社"編碼後的字符串, 我們通過UrlDecode解碼就可以得到原來用戶輸入了什麼關鍵字訪問了自己的網站, 一般的編程語言都提供瞭解碼工具, Java裏的是URLDecoder。

百度對關鍵字是使用GBK編碼,不過有些網站比如谷歌使用的是UTF8編碼,需要根據不同情況加以處理。

上面的參考文章列出各個搜索引擎的關鍵字,但是其實有很多已經是無效的(比如china的已經轉爲使用google的搜索服務),實際上還有效的列表如下(加上了後來的有道)

名稱 關鍵字 編碼
baidu wd/word GBK
sogou query GBK
yahoo p UTF-8
google q UTF-8
search.msn q UTF-8
youdao q/lq UTF-8
search.114.vnet.cn kw GBK

4 Java的編碼實現:

貼點代碼

(HttpUtils.java)

    /** 
     * 從當前請求得到請求來源 
     * 
     * @param request 
     * @return 
     */ 
    public static String getReferer(HttpServletRequest request) { 
        return request.getHeader("Referer"); 
    }

    /** 
     * #727 針對搜索引擎來源用戶的提示 
     * 
     * 從某個url裏面得到特定參數的值 
     * 
     * @param name 
     * @param url 
     * @return 
     */ 
    public static String getParameterFromUrl(String name, String url) { 
        if (!url.contains("?")) { 
            return ""; 
        } 
        String reval = ""; 
        url = url.substring(url.indexOf("?") + 1); 
        String[] pairs = url.split("&"); 
        for (String pair : pairs) { 
            if (pair.contains("=")) { 
                String pairName = pair.substring(0, pair.indexOf("=")); 
                if (name.equals(pairName)) { 
                    reval = pair.substring(pair.indexOf("=") + 1); 
                    return reval; 
                } 
            } 
        } 
        return reval; 
    }

    /** 
     * #727 針對搜索引擎來源用戶的提示 
     * 
     * 根據url取得搜索關鍵詞 
     * 
     * @param refererURL 
     *            request的來源url 
     * @return 
     */ 
    public static String getSearchKeyInRefererURL(String refererURL) { 
        String searchKey = ""; 
        if (StringUtils.isNotEmpty(refererURL)) { 
            try { 
                if (refererURL.contains("baidu.com")) { 
                    // wd/word 
                    searchKey = getParameterFromUrl("wd", refererURL); 
                    if (StringUtils.isEmpty(searchKey)) { 
                        searchKey = getParameterFromUrl("word", refererURL); 
                    } 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, 
                                StringUtils.ENCODE_GBK); 
                    } 
                } else if (refererURL.contains("sogou.com")) { 
                    // query 
                    searchKey = getParameterFromUrl("query", refererURL); 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, 
                                StringUtils.ENCODE_GBK); 
                    } 
                } else if (refererURL.contains("search.114.vnet.cn")) { 
                    // kw 
                    searchKey = getParameterFromUrl("kw", refererURL); 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, 
                                StringUtils.ENCODE_GBK); 
                    } 
                } else if (refererURL.contains("search.msn.com") 
                        || refererURL.contains("live.com")) { 
                    // q 
                    searchKey = getParameterFromUrl("q", refererURL); 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, null); 
                    } 
                } else if (refererURL.contains("yahoo.com") 
                        || refererURL.contains("yahoo.cn")) { 
                    // p 
                    searchKey = getParameterFromUrl("p", refererURL); 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, null); 
                    } 
                } else if (refererURL.contains("www.google")) { 
                    // q 
                    searchKey = getParameterFromUrl("q", refererURL); 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, null); 
                    } 
                } else if (refererURL.contains("www.youdao")) { 
                    // q or lq 
                    searchKey = getParameterFromUrl("q", refererURL); 
                    if (StringUtils.isEmpty(searchKey)) { 
                        searchKey = getParameterFromUrl("lq", refererURL); 
                    } 
                    if (StringUtils.isNotEmpty(searchKey)) { 
                        searchKey = StringUtils.urlDecode(searchKey, null); 
                    } 
                } 
            } catch (Exception e) { 
                log.error(e.getMessage()); 
                searchKey = ""; 
            } 
        } 
        return searchKey; 
    }

 

(SearchEngineHintFilter.java)

在請求過濾器裏面取得關鍵字, 進行搜索:

public void doFilter(ServletRequest request, ServletResponse response, 
            FilterChain chain) {

String refererURL = HttpUtils.getReferer(request); 

String searchKey = HttpUtils.getSearchKeyInRefererURL(refererURL); 
            if (StringUtils.isNotEmpty(searchKey)) { 
                log.debug("Got searchkey: " + searchKey+" |"+HttpUtils.getURL(httpRequest)); 
                httpRequest.setAttribute(WebConstants.REQUEST_SEARCH_KEYWORD, 
                        searchKey); 
                List<Map<String, String>> refTopics = doSearch(searchKey); 
                httpRequest.setAttribute(WebConstants.REQUEST_SEARCH_RESULT, 
                        refTopics); 
            }

}   

doSearch方法裏面調用了庖丁分詞, 根據關鍵字全文檢索站內文章 

5 其他:

提示框的CSS+JS置底 這個詳情請mockee來八卦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章