1. 程式人生 > >獲取搜尋引擎資訊及搜尋關鍵字

獲取搜尋引擎資訊及搜尋關鍵字

在做電子商務E流量分析的時候,需要實現一個功能:如果訪客是通過搜尋引擎的搜尋找到客戶網站的,要統計出訪客是通過哪個搜尋引擎訪問到頁面,並且統計出是通過 什麼關鍵字搜尋到該網站的。在網上google一下,發出對這方面的描述文件還是比較少的,在做這個功能的過程中有些經驗給人家分享一下。

實現這樣的功能,基本原理是獲取到來源地址,然後分析其中的內容,把所需要的搜尋引擎名稱和關鍵字取出。
獲取來源地址很簡單,在servlet 中可以通過HttpServletRequest.getHeader("Referer")方法取得,jsp頁面中可以通過 request.getHeader("referer")取得。取得來源地址後便可以通過分析得到的來源地址分析出我們所需要的內容。通常我們常用的搜 索引擎有以下14個。
http://www.google.com;
http://www.google.cn;
http://www.sogou.com;
http://so.163.com;
http://www.iask.com;
http://www.yahoo.com;
http://www.baidu.com;
http://www.3721.com;
http://www.soso.com;
http://www.zhongsou.com;
http://www.alexa.com;
http://www.search.com;
http://www.lycos.com;
http://www.aol.com;

  要獲取我們所需要的內容,我們必須分析 各個引擎的特性,由於各個搜尋引擎的格式不一樣,獲取到的來源地址必然也不一致,下面我們來分析一下各種搜尋引擎的地址格式。

   在搜尋引擎裡輸入關鍵字,點選搜尋之後位址列中的內容就是我們通過HttpServletRequest.getHeader("Referer")或 request.getHeader("referer")取得的來源地址。


google搜尋引擎:
http://www.google.com/search?hl= zh-N&newwindow=1&
q=%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80&
btnG= %E6%90%9C%E7%B4%A2&lr=

http://www.google.cn/search?hl= zh-N&newwindow=1&
q=%E6%B0%B8%E5%AE%89%E8%B7%AF%E7%81%AF&
btnG= %E6%90%9C%E7%B4%A2&meta=

從這裡我們可以得到我們所需要的搜尋引擎名稱和關鍵字。其中,搜尋引擎顯而易見,是google;而關鍵字呢?經過我仔細觀察、
測試後發現關鍵字是編碼後放 在引數q裡,也就是說
%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80和
%E6%B0 %B8%E5%AE%89%E8%B7%AF%E7%81%AF
就是輸入的關鍵字。


(有人會問,那btnG這個引數的值是什麼來頭,他也編過碼 啊?是用來幹嘛的呢?呵呵,它什麼來頭都沒有,什麼也沒幹,多餘的!你試試輸入關鍵字之後點選搜尋按鈕看看位址列,然後再試試輸入關鍵字之後回車,再看看 位址列,看出兩種做法在位址列中的一點點差別之後你就會明白的啦)

baidu搜尋引擎:
(1)http://www.baidu.com/s?ie=gb2312&bs=%CB%B3%B5%C2%BC%D2%BE%DF&sr=&z=&cl=3&f=8&
wd=%BD%F1%BF%C6%BF%C6%BC%BC&ct=0
(2)http://www.baidu.com/baidu?tn=nanlingcb&word=%CB%B3%B5%C2%BC%D2%BE%DF

baidu 搜尋引擎,這裡需要說明一下,當我們在通過在http://www.baidu.com中 輸入搜尋關鍵字,獲取的來源地址為(1)字串;當通過其它方式,比如在一些瀏覽器外掛中輸入關鍵字搜尋的獲取的來源地址為(2)字串。通過獲取來的這來源地,我也可以很容易的知道當前的搜尋引擎是baidu;而關鍵字呢?看看(1),這裡有兩個經過編碼的字串,到底哪個是關鍵字呢?wd的值是關鍵字!信我啦!那bs的值是什麼呢?你輸入關鍵字多搜尋幾次,看看你有什麼發現?發現了吧,bs是你上一次搜尋的關鍵字!這個我們不管,它不是我們所要的東 西。分析得知,在baidu搜尋引擎裡有兩個地方放關鍵字,一個地方是編碼後放在在引數wd裡,另外一個地方是編碼後放在word引數裡。明白了吧?:)


sogou搜尋引擎
http://www.sogou.com/web?query=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC
這個就沒這麼複雜了,我們通過字串可以知道搜尋引擎為sogou,關鍵字經編碼後放在引數query裡,這裡值為
%BD%F1%BF%C6%D0%C5 %CF%A2%BF%C6%BC%BC,有時候也會附帶多一些引數,但附帶的這些引數對我們來說是沒用的。

163搜尋引擎
http://cha.so.163.com/so.php?in=seek&c=26&key=032152284&q=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC
&x=61&y=19
這個也不復雜,分析得知,搜尋引擎名稱為163,關鍵字在引數q裡,這裡值為%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC


yahoo 搜尋引擎
http://search.cn.yahoo.com/search?p=%D3%C0%B0%B2%C2%B7%B5%C6&
source=toolbar_yassist_button&pid=58061_1006&ei=gbk

http://search.cn.yahoo.com/search?lp=%E4%B8%AD%E5%B1%B1%E5%8F%A4%E9%95%87%E7%81%AF%E9%A5%B0&
p=%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80&pid=&ei=UTF-8
很容易得到,搜尋引擎名稱為yahoo,那關鍵字是哪些呢?關鍵字是放在引數p裡,而引數lp的值跟baidu類似,也是上一次搜尋的關鍵字。

lycos 搜尋引擎
http://search.lycos.com/?query=website
這 個我們用得比較少,同樣我們通過這個字串得出搜尋引擎為lycos,關鍵字放在query裡.

3721搜尋引擎
http://seek.3721.com/index.htm?name=%D6%E9%BA%A3%CF%E3%D6%DE%C0%CD%CE%F1%CA%D0%B3%A1
容 易得到,搜尋引擎名稱為3721,關鍵字放在name裡

search搜尋引擎
http://www.search.com/search?lq=d%25E4%25B8%25AD%25E5%259B%25BDd&
q=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%9B%BD%E5%92%8C
這 個我們用得很少,也容易得到搜尋引擎名稱為search,關鍵字放在p裡,而lp放的是什麼呢?尚未弄清楚,
反正與我們所要的東西無關。

soso 搜尋引擎
http://www.soso.com/q?w=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC12&sc=web&
bs=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC1&ch=w.soso.pr&uin=&lr=chs&web_options=on
可 以看出搜尋引擎名稱為soso,關鍵字放在引數w裡,需引數bs的值跟baidu相似,是上一次搜尋的關鍵字

zhongsou搜尋引擎
http://p.zhongsou.com/p?w=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC&l=&jk=&k=&r=&aid=&pt=1&dt=2
可 以看出搜尋引擎名稱為zhongsou,關鍵字在引數w裡。

alexa搜尋引擎
http://www.alexa.com/search?q=%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80
得出搜尋引擎名稱為zhongsou,關鍵字放在引數q裡。

    對各種搜尋引擎的url的分析已完成,大家都對這些常用的搜尋引擎的url的格式有所瞭解了,下面我們看看怎樣從我們所取得的這些字串中得到我們所要的資訊,也就是怎樣從這些字串中提取我們所需的搜尋引擎名稱和搜尋關鍵字.這裡理所當然使用功能強大的正則表示式了.好,現在我們逐個逐個地分析各個搜尋引擎用什麼正則表示式提取我們所需要的內容.
首先還是先分析 google搜尋引擎:
上面已經提到我們取得的google搜尋引擎的地址是這樣的:
http://www.google.com/search?hl= zh-N&newwindow=1
&q=%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80&
btnG= %E6%90%9C%E7%B4%A2&lr=

http://www.google.cn/search?hl= zh-N&newwindow=1
&q=%E6%B0%B8%E5%AE%89%E8%B7%AF%E7%81%AF&
btnG= %E6%90%9C%E7%B4%A2&meta=

其 實它還有一種形式是這樣的:
(3)http://www.google.com/custom?hl=zh-CN&inlang=zh-CN&ie=GB2312&oe=GB2312&newwindow=1&
client=pub3261928361684765&cof=FORID%3A1%3BGL%3A1%3BBGC%3AFFFFFF%3BT%3A%23000000%3BLC%3A
%230000ff%3BVLC%3A%23663399%3BALC%3A%230000ff%3BGALT%3A%23008000%3BGFNT%3A
%230000ff%3BGIMP%3A%230000ff%3BDIV%3A%23336699%3BLBGC%3A336699%3BAH%3Acenter%3B
&q=%C5%B7%C2%FC%D5%D5%C3%F7&lr=
OH,my god,是不是看得頭暈了?先不要暈,往下看你就不會覺得暈的啦....

我們仔細觀察一下,這三種格式都有一個共通點,大家有沒有發現呢?就是 他的格式都是這樣的:


http://www.google.[...]/[...]&q= [關鍵字][...]


[...]表示有一個以上的字元.

就如(2)我們在裡面放入一些[]就可以看得更清楚了:
http://www.google.[cn]/[search?hl=zh-CN&newwindow=1]
&q=[%E6%B0%B8%E5%AE%89%E8%B7%AF%E7%81%AF][&btnG=%E6%90%9C%E7%B4%A2&meta=]

看明白了吧?看明白了我們就接下去了.於是我們可以得出google搜尋引擎的正則表示式了:

http:\\/\\/www\\.google \\.[a-zA-Z]+\\/.+[\\&\\?]q=[^\\&]*。

   現在解釋一下這個正則表示式的意思。
http:\\/ \\/www\\.這一段是匹配http://www.
,為什麼這裡多了這麼多\呢?因為字元 '/'和字元'.'在正則表示式中有特殊意義,要用'\'對這兩個字元轉義,'/'通過'\/'轉義,相似的.也通過'\.'轉義,而字元'\'在 java裡也是一個特殊字元,本身也需要轉義,所以'\/'寫成'\\/',類似的'\.'寫成'\\.';

接下來google\\.[a-zA-Z]+ \\/.+匹配google.com/search?hl=zh-CN&newwindow=1,這裡解釋一下[a-zA-Z]+,意思是最少有 一個(包括一個)以上英文字母,[a-zA-Z]表示從a到z,從A到Z的字元,+表示至少一個以上,[\\&\\?]q=[^\\&]*匹配的是&q=%E6%B0%B8%E5%AE%89%E8%B7%AF%E7%81%AF,[\\&\\?],表示字元&或字元?由於&和?都是特殊字元,所以都要用轉義符轉義,q=[^\\&]*表示q=後面是零個(包括零個)以上的非& 字元,[^\\&]表示不為&的字元,為什麼不為&呢,因為&後面的字元也經不再屬於引數q的值了,我們要取的是q=之 後,字元&之前的字串.這個正則表示式的解釋就到此了。現在這個正則表示式已經可以從眾多的獲取過來的來源地址中分辯出哪些是google搜尋引擎了,但是有一個問題,假如以後google搜尋引擎不是這樣,換成http://search.google.com/search?hl=zh-CN&newwindow=1&q=%E6%B0%B8%E5%AE%89%E8%B7%AF%E7%81%AF
&btnG=%E6%90%9C%E7%B4%A2&meta= 呢,

那這個正則表示式就不合適了,怎樣能在以後改動之後我們寫的正則表示式還適用呢?很簡單,我們把它改成這個樣子:\\.google\\.[a- zA-Z]+\\/.+[\\&\\?]q=[^\\&]*,意思是我們不必匹配http://www這 一串字串。這樣如果google搜尋引擎做了類似http://search.google.com/..... 的修改,我們寫的正則表示式也適用了,那假如它把域名也改了就沒得說了,:);還有一種情況,在位址列裡輸入www.google.com:80/也可以正常訪問google,也就是說還有 一種情況就是加埠的訪問,這種情況也要考慮到,因此之前我們的正則表示式應改成:\\.google\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=[^\\&]*, (:\\d{1,}){0,1}是什麼意思呢?他匹配類似":80"也就是說冒號(:)後跟1個以上的數字字元,而埠是可選的,並且如果出現只會出現一 次,所以用{0,1}.這個正則表示式的用途是用於獲取關鍵字,所以這裡我把關鍵字部分劃分為一個組(這在下面會用到),因此,最終的正則表示式為:

\\.google\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)

對 google搜尋引擎已經說得很詳細,接下來的我就簡略的說說了,原理都差不多的了。


baidu搜尋引擎:
分 析得知baidu搜尋引擎的正則表示式為:
\\.baidu\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]wd=([^\\&]*) 或
\\.baidu\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]word=([^\\&]*)

sogou 搜尋引擎
http://www.sogou.com/web?query=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC
正 則表示式:
\\.sogou\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]query=([^\\&]*)

yahoo搜尋引擎
正 則表示式:
\\.yahoo\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]p=([^\\&]*)

lycos 搜尋引擎
http://search.lycos.com/?query=website
正 則表示式:
\\.lycos\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.*[\\&\\?]query=([^\\&]*)

3721 搜尋引擎
http://seek.3721.com/index.htm?name=%D6%E9%BA%A3%CF%E3%D6%DE%C0%CD%CE%F1%CA%D0%B3%A1
http://seek.3721.com/index.htm?q=%D6%E9%BA%A3%CF%E3%D6%DE%C0%CD%CE%F1%CA%D0%B3%A1
正 則表示式:
\\.3721\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]p=([^\\&]*) 或
\\.3721\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]name=([^\\&]*)

search 搜尋引擎
正則表示式:
\\.search\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)

soso搜尋引擎
正 則表示式:
\\.soso\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]w=([^\\&]*)

zhongsou搜尋引擎
http://p.zhongsou.com/p?w=%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC&l=&jk=&k=&r=&aid=&pt=1&dt=2
正 則表示式:
\\.zhongsou\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]w=([^\\&]*)

alexa搜尋引擎
http://www.alexa.com/search?q=%E4%BB%8A%E7%A7%91%E4%BF%A1%E6%81%AF%E7%A7%91%E6%8A%80
正 則表示式:
\\.alexa\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)

iask搜尋引擎
正則表示式:
\\.iask\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]k=([^\\&]*) 或
\\.iask\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]_searchkey=([^\\&]*)


好了,正則表示式已經寫出來了,事情已經完成一半了。現在我們把話題轉一下,等會我們再轉回來,現在我們先看看如何獲取搜尋引擎的名稱。同樣,也 需要用正則表示式,正則表示式實在太強了:)。
我們可以通過以下的正則表示式匹配到google搜尋引擎:
http:\\/\\/.* \\.google\\.com(:\\d{1,}){0,1}\\/或
http:\\/\\/.*\\.google\\.cn(:\\d{1,}){0,1}\\/

類 似的也可以匹配其它搜尋引擎,我把他們寫在一起:
http:\\/\\/.*\\.(google\\.com(:\\d{1,}){0,1}\\/|google\\.cn(:\\d{1,}){0,1}\\/|
baidu\\.com(:\\d{1,}){0,1}\\/|yahoo\\.com(:\\d{1,}){0,1}\\/|
iask\\.com(:\\d{1,}){0,1}\\/|sogou\\.com(:\\d{1,}){0,1}\\/|
163\\.com(:\\d{1,}){0,1}\\/|lycos\\.com(:\\d{1,}){0,1}\\/|
aol\\.com(:\\d{1,}){0,1}\\/|3721\\.com(:\\d{1,}){0,1}\\/|
search\\.com(:\\d{1,}){0,1}\\/|soso.com(:\\d{1,}){0,1}\\/|
zhongsou\\.com(:\\d{1,}){0,1}\\/|alexa\\.com(:\\d{1,}){0,1}\\/)
通過以下程式可以獲取到搜尋引擎的名稱:

import java.util.regex.*;
public class GetEngine
{
public static void main(String[] arg)
{
   GetEngine engine=new GetEngine();
  
   String referer="http://www.baidu.com/s?wd=java%D1%A7%CF%B0%CA%D2";
   String engineName=engine.getSearchEngine(referer);
   System.out.println("搜尋引擎名稱:"+engineName);
}
public String getSearchEngine(String refUrl) {
    if(refUrl.length()>11)
    {
       //p是匹配各種搜尋引擎的正則表示式
      Pattern p = Pattern.compile("http:\\/\\/.*\\.(google\\.com(:\\d{1,}){0,1}\\/|
        google\\.cn(:\\d{1,}){0,1}\\/|baidu\\.com(:\\d{1,}){0,1}\\/|
        yahoo\\.com(:\\d{1,}){0,1}\\/|iask\\.com(:\\d{1,}){0,1}\\/|
        sogou\\.com(:\\d{1,}){0,1}\\/|163\\.com(:\\d{1,}){0,1}\\/|
        lycos\\.com(:\\d{1,}){0,1}\\/|aol\\.com(:\\d{1,}){0,1}\\/|
        3721\\.com(:\\d{1,}){0,1}\\/|search\\.com(:\\d{1,}){0,1}\\/|
        soso.com(:\\d{1,}){0,1}\\/|zhongsou\\.com(:\\d{1,}){0,1}\\/|
        alexa\\.com(:\\d{1,}){0,1}\\/)");
      Matcher m = p.matcher(refUrl);
      if (m.find())//如果來源地址可以匹配以上的pattern
      {
//因為m.group(0)是域名,m.group(1)才是我們最合適我們所要的
        return insteadCode(m.group(1),"(\\.com(:\\d{1,}){0,1}\\/|\\.cn(:\\d{1,}){0,1}\\/|
\\.org(:\\d{1,}){0,1}\\/)","");//把.com,.cn,.org替換為""
      }
    }
    return "未發現搜尋引擎";
}
public String insteadCode(String str,String regEx,String code){
    Pattern p=Pattern.compile(regEx);
    Matcher m=p.matcher(str);
    String s=m.replaceAll(code);
    return s;
}
}

通過以上的程式碼即可得出搜尋引擎名稱了,似乎任務完成一大半了。只是接著下來的要做的事情比之前所做的要麻煩點點,麻煩就麻煩在編碼上。
現在我樣回過頭看我們上面寫的一大堆各種搜尋引擎的正則表示式。
由於這裡要大量的字串操作,這裡使用StringBuffer來做字串的連線。
StringBuffer sb=new StringBuffer();
sb.append("\\.google\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)")
.append("|\\.iask\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]k=([^\\&]*)")
.append("|\\.iask\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]_searchkey=([^\\&]*)")
.append("|\\.sogou\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]query=([^\\&]*)")
.append("|\\.163\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)")
.append("|\\.yahoo\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]p=([^\\&]*)")
.append("|\\.baidu\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]wd=([^\\&]*)")
.append("|\\.baidu\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]word=([^\\&]*)")
.append("|\\.lycos\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.*[\\&\\?]query=([^\\&]*)")
.append("|\\.aol\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]encquery=([^\\&]*)")
.append("|\\.3721\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]p=([^\\&]*)")
.append("|\\.3721\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]name=([^\\&]*)")
.append("|\\.search\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)")
.append("|\\.soso\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]w=([^\\&]*)")
.append("|\\.zhongsou\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]w=([^\\&]*)")
.append("|\\.alexa\\.[a-zA-Z]+(:\\d{1,}){0,1}\\/.+[\\&\\?]q=([^\\&]*)");

這個正則表示式是把所有搜尋引擎用或"|"連線起來,因為只要匹配其中一個搜尋引擎的正則表示式就可以。
前面已經說到,關鍵字是經過編碼 的,我們直接取出的關鍵字會像%BD%F1%BF%C6%D0%C5%CF%A2%BF%C6%BC%BC12,
這樣的關鍵字我們無法讀懂,因些需要對這 些關鍵進行反編碼,這要用到java.net.URLDecoder.decode(String s,String enc),這個方法有兩個引數,一個引數是要進行反編碼的字串,另一個是指定的字符集。第一個引數很簡單,只要我們把取得的關鍵放到這個引數裡,至於第 二個引數怎樣呢?這裡我只討論中文的情況,這些搜尋引擎有兩種字符集編碼方式,一種是UTF-8,另外一種是GBK。
只有GBK一種編碼方式的搜 索引擎:
3721,iask,sogou,163,baidu,soso,zhongsou
只有UTF-8一種編碼方式的搜尋引擎:
lycos,aol,search,alexa
有 兩種編碼方式的:
google,yahoo

只有一種編碼方式的問題容易解決,有兩種編碼方式的怎辦呢?辦法總比問題多,其實採用哪一個編碼方工,它是有”暗示“的,對於google,大多數情況下它是採用UTF-8的編碼方式,我們在瀏覽器的位址列上輸入www.google.com搜尋的都是以這種方式來編碼的,但有種情況如:
http://www.google.com/custom?hl=zh-CN&inlang=zh-CN&ie=GB2312&oe=GB2312&newwindow=1&client=pub-3261928361684765&
cof=FORID%3A1%3BGL%3A1%3BBGC%3AFFFFFF%3BT%3A%23000000%3BLC%3A%230000ff
%3BVLC%3A%23663399%3BALC%3A%230000ff%3BGALT%3A%23008000%3BGFNT%3A%230000ff%3BGIMP%3A
%230000ff%3BDIV%3A%23336699%3BLBGC%3A336699%3BAH%3Acenter%3B&q=%C5%B7%C2%FC%D5%D5%C3%F7&lr=

這種情況下就不一定是UTF-8編碼了,這種情況下以ie這個引數指定,這裡ie=gb2312,所以編碼方式為gb2312,而gb2312是gbk的字 集,所以這裡我們用gbk而不用gb2312;對於yahoo情況類似,只不過yahoo在大多數情況下使用GBK編碼,如:
http://search.cn.yahoo.com/search?p=%C5%B7%C2%FC%BF%C6%BC%BC%CA%B5%D2%B5
&source=toolbar_yassist_button&pid=54554_1006&f=A279_1
就是GBK編碼,但這種情況:
http://search.cn.yahoo.com/search?ei=gbk&fr=fp-tab-web-ycn&source=errhint_up_web
&p=%BD%F1%BF%C6&meta=vl%3Dlang_zh-CN%26vl%3Dlang_zh-TW&pid=ysearch
就 用ei引數裡指定的紡碼方式了,這裡有可能指定的是gbk,也有可能指定的是UTF-8。
根據以上的解釋,於是有以下的程式來獲得各種搜尋引擎的關鍵字:

import java.util.regex.*;
import java.sql.*;
import java.net.URLDecoder;
import java.io.*;
public class GetKeyword
{
public static void main(String[] arg)
{
   String referer="http://www.baidu.com/s?wd=java%D1%A7%CF%B0%CA%D2";
   if(arg.length!=0)
   {
    referer=arg[0];
   }
   GetKeyword getKeyword=new GetKeyword();
   String searchEngine=getKeyword.getSearchEngine(referer);
   System.out.println("searchEngine:"+searchEngine);
   System.out.println("keyword:"+getKeyword.getKeyword(referer));
}
public String getKeyword(String refererUrl)
   {
     StringBuffer sb=new StringBuffer();
     if(refererUrl!=null)
     {
       sb.append("(google\\.[a-zA-Z]+/.+[\\&|\\?]q=([^\\&]*)")
           .append("|iask\\.[a-zA-Z]+/.+[\\&|\\?]k=([^\\&]*)")
           .append("|iask\\.[a-zA-Z]+/.+[\\&|\\?]_searchkey=([^\\&]*)")
           .append("|sogou\\.[a-zA-Z]+/.+[\\&|\\?]query=([^\\&]*)")
           .append("|163\\.[a-zA-Z]+/.+[\\&|\\?]q=([^\\&]*)")
           .append("|yahoo\\.[a-zA-Z]+/.+[\\&|\\?]p=([^\\&]*)")
           .append("|baidu\\.[a-zA-Z]+/.+[\\&|\\?]wd=([^\\&]*)")
           .append("|baidu\\.[a-zA-Z]+/.+[\\&|\\?]word=([^\\&]*)")
           .append("|lycos\\.[a-zA-Z]+/.*[\\&|\\?]query=([^\\&]*)")
           .append("|aol\\.[a-zA-Z]+/.+[\\&|\\?]encquery=([^\\&]*)")
           .append("|3721\\.[a-zA-Z]+/.+[\\&|\\?]p=([^\\&]*)")
           .append("|3721\\.[a-zA-Z]+/.+[\\&|\\?]name=([^\\&]*)")
           .append("|search\\.[a-zA-Z]+/.+[\\&|\\?]q=([^\\&]*)")
           .append("|soso\\.[a-zA-Z]+/.+[\\&|\\?]w=([^\\&]*)")
           .append("|zhongsou\\.[a-zA-Z]+/.+[\\&|\\?]w=([^\\&]*)")
           .append("|alexa\\.[a-zA-Z]+/.+[\\&|\\?]q=([^\\&]*)")
           .append(")");
       Pattern p = Pattern.compile(sb.toString());
       Matcher m = p.matcher(refererUrl);
       return decoderKeyword(m,refererUrl);
     }
     return null;
}
public String decoderKeyword(Matcher m,String refererUrl)
{
   String keyword=null;
   String encode="UTF-8";
   String searchEngine=getSearchEngine(refererUrl);
   if(searchEngine!=null)
   {
     if ((checkCode("3721|iask|sogou|163|baidu|soso|zhongsou",searchEngine)
	 ||(checkCode("yahoo",searchEngine)&&!checkCode("ei=utf-8",refererUrl.toLowerCase()))))
     {
       encode = "GBK";
     }
     
     if (m.find())
     {
       for (int i = 2; i <= m.groupCount(); i++)
       {
         if (m.group(i) != null)//在這裡對關鍵字分組就用到了
         {
           try
           {
             keyword = URLDecoder.decode(m.group(i), encode);
           }
           catch(UnsupportedEncodingException e)
           {
             System.out.println(e.getMessage());
           }
           break;
         }
       }
     }
   }
   return keyword;
}
public String getSearchEngine(String refUrl) {
    if(refUrl.length()>11)
    {
      //p是匹配各種搜尋引擎的正則表示式
      Pattern p = 
	  Pattern.compile("http:\\/\\/.*\\.(google\\.com(:\\d{1,}){0,1}\\/|
       google\\.cn(:\\d{1,}){0,1}\\/|baidu\\.com(:\\d{1,}){0,1}\\/|
       yahoo\\.com(:\\d{1,}){0,1}\\/|iask\\.com(:\\d{1,}){0,1}\\/|
       sogou\\.com(:\\d{1,}){0,1}\\/|163\\.com(:\\d{1,}){0,1}\\/|
       lycos\\.com(:\\d{1,}){0,1}\\/|aol\\.com(:\\d{1,}){0,1}\\/|
       3721\\.com(:\\d{1,}){0,1}\\/|search\\.com(:\\d{1,}){0,1}\\/|
       soso.com(:\\d{1,}){0,1}\\/|zhongsou\\.com(:\\d{1,}){0,1}\\/|
       alexa\\.com(:\\d{1,}){0,1}\\/)");
      Matcher m = p.matcher(refUrl);
      if (m.find())
      {
        return insteadCode(m.group(1),
		"(\\.com(:\\d{1,}){0,1}\\/|\\.cn(:\\d{1,}){0,1}\\/|\\.org(:\\d{1,}){0,1}\\/)","");
      }
    }
    return "未發現有搜尋引擎";
}
public String insteadCode(String str,String regEx,String code){
    Pattern p=Pattern.compile(regEx);
    Matcher m=p.matcher(str);
    String s=m.replaceAll(code);
    return s;
}
public boolean checkCode(String regEx,String str){
    Pattern p=Pattern.compile(regEx);
    Matcher m=p.matcher(str);
    return m.find();
}
}
轉載自:http://www.java3z.com/cwbwebhome/article/article5/51093.html?id=2723