2010年4月3日星期六

获得来自搜索引擎的关键字

  一般情况下通过关键词进入的页面都是用户想要的内容,对于某些搜索搜录与关键词相关度不是很高的页面(例如列表页),我们需要根据用户搜索的关键词对用户进行引导,从而提高用户的体验,也可以提高网页的PV。

  本文的原理是通过获取来源页面,分析来源URL的结构,提取出关键字,这些都是比较简单的东西。本文阐述重点是如何区分出几种常见的URL编码方式,然后进行相应的解码。因为应用是在ASP中进行,因此本文若有代码相关的例子,均是在ASP下调试通过的。其他语言下思想相同,且实现相对简单些。

  提取各个搜索引擎的关键字

  现在的各大搜索引擎全是基于GET请求方式的,即在URL后面带有一串参数。例如:我搜索“秋寒博客”

  谷歌:http://www.google.cn/search?sourceid=navclient&hl=zh-CN&ie=UTF-8&rlz=1T4GGLL_zh-CN___CN352&q=%e7%a7%8b%e5%af%92%e5%8d%9a%e5%ae%a2

  百度:http://www.baidu.com/s?wd=%C7%EF%BA%AE%B2%A9%BF%CD

  必应:http://cn.bing.com/search?q=%E7%A7%8B%E5%AF%92%E5%8D%9A%E5%AE%A2&form=QBLH&filt=all

  谷歌和Google的 q=%e7%a7%8b%e5%af%92%e5%8d%9a%e5%ae%a2 ,百度的 wd=%C7%EF%BA%AE%B2%A9%BF%CD ,必应的 q=%E7%A7%8B%E5%AF%92%E5%8D%9A%E5%AE%A2 中带下划线部分就是关键词。 其他搜索引擎也大致相同,通过URL就可以看出关键词的字段是哪个,然后可以通过正则将关键词提出。

  提取主流搜索关键词的正则如下:

  (?:yahoo.+?[?|&]p=|openfind.+?query=|google.+?q=|lycos.+?query=|onseek.+?keyword=|search.tom.+?word=|search.qq.com.+?word=|zhongsou.com.+?word=|search.msn.com.+?q=|yisou.com.+?p=|sina.+?word=|sina.+?query=|sina.+?_searchkey=|sohu.+?word=|sohu.+?key_word=|sohu.+?query=|163.+?q=|baidu.+?wd=|baidu.+?kw=|baidu.+?word=|3721.com.+?p=|Alltheweb.+?q=|soso.+?w=|115.+?q=|youdao.+?q=|sogou.+?query=|bing.+?q=|114.+?kw=)([^&]*)

   以上正则是我根据网上的正则有所修改,让其支持soso、115、youdao、sogou、bing(必应)、114(或118114)这些搜索,感谢作者提供。因为网上转载太多,尚未注明原出处,因此我也无法标明原作者。

  编码类型的识别

  GB2312和UTF-8

  从上面的例子我们可以看出,同样是搜索“秋寒博客”,但是不同的搜索对URL编码后,形成的字符串也不同。谷歌和必应下面是“%e7%a7%8b%e5%af%92%e5%8d%9a%e5%ae%a2”,而在百度却是“%C7%EF%BA%AE%B2%A9%BF%CD”。相信对网页编码了解的朋友都应该了解这是怎么回事,不同的页面编码(charset)对相同的字符进行编码后,产生的编码也是不同的。UTF-8默认产生的是UTF-8的编码,默认解码也是UTF-8。GB2312等也一样的。谷歌和必应用的是UTF-8编码,而百度用的是GB2312编码,就造成了相同的关键词在不同的搜索下产生了不同的字符串。

  对于UTF-8和GB2312的解码都可以实现,但是如果不知道目标是什么编码方式,就不知道如何去解码了。如上面的两个字符串,初给你看,看不来是用何种编码方式。当然第一反应是通过搜索来判断编码方式,这种方法确实可行也有效。但是看看上面的正则,如果用这种方法,那么一个 if 后面要跟很多的 or 才行。网上一般用的也是这样的方法,我觉得这个不是最好的方法。我们得知的信息有:1、%xx%xx格式都是URL编码(UTF-8或GB2312);2、GB2312中汉字要两组%xx组成一个汉字,UTF-8要三组%xx组成一个汉字;3、如果用UTF-8解码方式去解GB2312的编码就会出现乱码。

  单从长度和编码的范围我们根本无法辨别编码方式,只能通过其他方式来判断。根据上面3点,我们可以做一个假设:如果用UTF-8解码方式来解GB2312的编码会出现什么情况?因为UTF-8是有三组%xx组成的,而GB2312是由两组%XX组成的,如果用UTF-8的解码方式去解GB2312且能解码成功,那解码后的字符的长度一定会变短。例如:GB2312URL编码的“秋寒博客”(%C7%EF%BA%AE%B2%A9%BF%CD)用UTF-8解码,若能解码成功,解码后的字符长度会是2个半汉字。如果不能解码成功,不用说就是GB2312编码方式了。

  OK,至此我们初步已经知道如何去识别URL的编码类型了,步骤如下:

  1、获取关键字编码串;

  2、取得编码串的组数(x),例如:“%C7%EF%BA%AE%B2%A9%BF%CD 为8组;

  3、用UTF-8解码方式去解取得的编码串;

  4、如果解码失败(即程序出错)跳到第 8 步;

  5、如果解码成功,取得解码后的字符串长度(y),与全面的编码串的组数除以3比较;

  6、如果 x!=y 那么跳转到第 8 步;

  7、如果 x=y 那么得到的字符串即为关键字;

  8、用GB2312方式解码,得到的字符串为关键字;

  上面步骤中,有几点需要注意:

  1、第1步中需要将非汉字的URL转义及英文去掉;

  2、第2、3、5步中的编码串为上面提到的字符串;

  3、第7、8步中解码需要对原字符串进行;

  UNICODE

  在测试的过程中,发现soguo从网页跳到图片去的时候,会将URL编码方式改为UNICODE。UNICODE的方式相对比较好区分,即判断是否为uxxxx或%uxxxx的形式即可。这个相对简单,只分享在ASP中的解码函数。

  以下代码来自CSDN论坛:

  方法一:

  response.Write vbsUnEscape("u5c0fu867eu7c73")

  Function vbsUnEscape(str)'解密

    dim i,s,c

    s=""

    For i=1 to Len(str)

      c=Mid(str,i,1)

      If Mid(str,i,2)="u" and i<=Len(str)-5 Then

        If IsNumeric("&H" & Mid(str,i+2,4)) Then

          s = s & CHRW(CInt("&H" & Mid(str,i+2,4)))

          i = i+5

        Else

          s = s & c

        End If

      ElseIf c="%" and i<=Len(str)-2 Then

        If IsNumeric("&H" & Mid(str,i+1,2)) Then

          s = s & CHRW(CInt("&H" & Mid(str,i+1,2)))

          i = i+2

        Else

          s = s & c

        End If

      Else

        s = s & c

      End If

    Next

    vbsUnEscape = s

  End Function

  方法二:

  s = "u5c0fu867eu7c73"

  s = Replace(s, "u", "%u")

  Response.Write Unescape(s)

  在C#中也没有发现能识别URL编码格式的函数或方法,不知在PHP和JAVA下有没有更好的方法呢?欢迎大家讨论。

  来源:读者沈力投稿,原文地址