url normalization

来源:互联网 发布:房地产数据分析公司 编辑:程序博客网 时间:2024/05/04 20:06

在爬虫中需要将url变为唯一、合法的形式以避免重复爬行,因此正规化要将其中必须用urlencode的地方全部encode,不需要的即时在原始url中已经encode也要decode(保留字符和非保留字符使用原RFC规定的,参考维基百科url normalization一文,与浏览器有一定出入),且所有的url encode都要使用大写形式,域名后面的冗余点号必须去掉,域名必须全部小写,域名部分还要按照IDN的规定使用punycode进行编码(暂未实现),路径部分要消除.和..的冗余,同事对于超出范围的url要能容错(如:http://sports.163.com/./xj/../.. => http://sports.163.com/),query strings中的key-value对排序之后连接。对于空格统一使用+。由于逻辑判断较多,最后写成了有限状态机的形式,以使逻辑清晰。相当于有两层词法分析,第一层按照需要urlencode或者decode之后生成一些字节,第二层则以第一层输出为输入,进行normalize。其中的状态机终态不互为前缀,这样状态迁移的过程就不必保存上次匹配了。

值得商榷的地方是空格全部使用+,而这时早期的规定,不知道是否所有服务器都支持(这样实现略简单些)。另外输入的串必须以/0结束,也就是传入的未归一的url中不能包含0字节。不过目前还没有在中间有0字节的需求。如果把诸多的if给成switch经优化后可能会加快。

google url貌似也完成类似功能。这里贴出fileNormalize的代码。

 

几个测试用例:

 

# 主机名称是否变成小写
slot {
  isgbk: false
  url: "http://www.ExAmple.com"
  base: "http://www.ExAmple.com"
  answer: "http://www.example.com/"
}

# 主机后面的点号是否去掉
slot {
  isgbk: false
  url: "http://sports.163.com../"
  base: "http://sports.163.com"
  answer: "http://sports.163.com/"
}

# 冗余的路径,非法路径消除,多余的/,.,..消除
slot {
  isgbk: false
  url: "http://sports.163.com/yc/../../../xj//index.html"
  base: "http://sports.163.com"
  answer: "http://sports.163.com/xj/index.html"
}

# 路径中的.和y被转义,是否再转回来
slot {
  isgbk: false
  url: "http://sports.163.com/%79c/%2e%2E/xj"
  base: "http://sports.163.com/"
  answer: "http://sports.163.com/xj"
}

# 不完整的url编码是否会被decode
slot {
  isgbk: false
  url: "http://www.baidu.com/s?wd=%%4%20abc"
  base: "http://www.baidu.com/"
  answer: "http://www.baidu.com/s?wd=%25%254+abc"
}

# 主机部分是否转成punycode
slot {
  isgbk: false
  url: "gsjs.htm"
  base: "http://北京风机厂.中国"
  answer: "http://xn--1lq90ihj568dev0d.xn--fiqs8s/gsjs.htm"
}

# 分段标志符是否去掉
slot {
  isgbk: false
  url: "http://www.example.com/bar.html#section1"
  base: "http://www.example.com"
  answer: "http://www.example.com/bar.html"
}

# querystring是否排序、消除了重复
slot {
  isgbk: false
  url: "http://www.example.com/display?lang=chn&article=fred&&lang=en"
  base: "http://www.example.com"
  answer: "http://www.example.com/display?article=fred&lang=en"
}

# 需要urlencode需转,不需要urlencode的要转回来,同时url编码部分必须用大写,空格统一用+
slot {
  isgbk: true
  url: "http://www.baidu.com/s?w%64=%4aack 你%20好"
  base: "http://www.baidU.com/"
  answer: "http://www.baidu.com/s?wd=Jack+%C4%E3+%BA%C3"
}

原创粉丝点击