一个基于Java的开源URL嗅探器

澳门新葡亰3522平台游戏 1

本文由码农网 –
Dee1024原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

正则表达式的语法就不多说了,大家可以自己搜索查阅相关资料学习。本文所举例子是在《JavaScript语言精粹》上看到的,看完之后对正则表达式有了进一步的理解,故分享之。

这是一个可以检测并规范化文本中的URL地址的Java库。

例子

澳门新葡亰3522平台游戏 1

//这是一个用来匹配URL的正则表达式,分组获取不同部分的信息
var parse_url = /^(?:([A-Za-z]+):)?(/{0,3})([0-9.-A-Za-z]+)(?::(d+))?(?:/([^?#]*))?(?:?([^#]*))?(?:#(.*))?$/;
var url = “”;
var result = parse_url.exec(url);
var names = [“url”, “scheme”, “slash”, “host”, “port”, “path”, “query”, “hash”];var i;
for (i = 0; i < names.length; i++) {
 document.writeln(names[i] + “: ” + result[i] + ” “); }
//这段代码的输出结果如下:
url:  scheme: http slash: //
host: www.ora.com port: 80 path: goodparts query: q hash: fragment

今天,我们很高兴做一个分享,因为我所在的 Linkedin
公司 开源了我们做的一个ULR探测工具:URL-Detector  Java
库。

解析
下面让我们分解parse_url的各个部分,看看它是如何工作的:

Linkedin 在每一秒钟,会检查数十万数量级的 URLs 。这些 URL
可能是来自恶意软件或者钓鱼网站的,为了保障我们每一个用户有一个安全的浏览体验,同时防止潜在的危险,我们后端的内容检查服务程序会检查所有由用户产生的内容。为了在这每秒数十万规模的用户内容上检测不良的
URL,我们要有能够在快速此规模上提取文本中URL 的方法。

^

我们的服务器中的 URL地址有两种形式:

^字符表示此字符串的开始,它是一个锚,指引exec不要跳过那些不像URL的前缀,只匹配那些从开头就像URL一样的字符串。

  • 一种是单一的 URL
  • 一种是在一大块的文本内容中

(?:([A-Za-z]+):)?

如果发送过来的是单一的 URL,我们可以通过我们的内容检查服务直接验证;

这个因子匹配一个协议名,但仅当它后面跟随一个 :(冒号)的时候才匹配。(?:
. . .)表示一个非捕获型分组(noncapturing group)。后缀 ?
表示这个分组是可选的,它表示重复0次或1次。( . .
.)表示一个捕获型分组。一个捕获型分组会复制它所匹配的文本,并把其放到result数组里。每个捕获型分组都会被指定一个编号。第一个捕获型分组的编号是1,所以该分组所匹配的文本副本会出现在result[1]中。
[ . .
.]表示一个字符类。A-Za-z这个字符类包含26个大写字母和26个小写字母。连接字符

如果发送过来的是大块的文本内容,我们会先通过我们的URL探测器 ,经过搜索算法来验证这个文本是否有潜在危险的URL地址;

  • 表示范围从A-Z。后缀 +
    表示这个字符类会被匹配一次或多次。这个组后面跟着字符 :
    ,它会按字面进行匹配。 

在我介绍URL探测器是如何工作的和它所能提供给的功能之前,让我们先来了解一下我们做这个项目的动机。

(/{0,3})

我们的目标是:检测出尽可能多的恶意链接,但是我们不希望紧紧局限于检测在 RFC
1738 中定义的URL地址,而是希望可以检测出任何能够在真正的浏览器地址栏中输入并且可以访问到的URL地址。因为,一个浏览器的地址栏中对
URL 的定义比起 在 RFC
1738 定义的来说,是非常松散的。同时,很多浏览器有不同的行为,所以,我们要找到一种URL文本规则能够被大部分流行的浏览器解析,它不是像RFC中定义语法那样简单。

这个因子是捕获型分组2,匹配//。 /表示应,该匹配 / (斜杠)。它用
(反斜杠)来进行转义,这样它就不会被错误地解释为这个正则表达式的结束符。后缀
{0,3} 表示 / 会匹配0~3次。

最初,我们开始第一种解决方案,基于正则表达式。它可以帮我们检测到许多潜在的网址,其中有不少却是真的有潜在危险的,但是其中也有不少是没有的,而且有许多有危险的地址被遗漏了。用这种方式,为了抓取更多的地址这是一个反复匹配的过程,这可能出现一些不状况,比如,一个简单URL匹配的正则:

([0-9.-A-Za-z]+)

Regex:
(ftp|http|https)://(w+:{0,1}w*@)?(S+)(:[0-9]+)?(/|/([w#!:.?+=&%@!-/]))?

澳门新葡亰3522平台游戏,这个因子是捕获型分组3。它会匹配一个主机名,由一个或多个数字、字母以及 .
或 – 字符组成。- 会被转义为 – 以防止与表示范围的连字符相混淆。

然后,如果你想检测到不包含 scheme 的
URL,对应修改正则如下,这是其中一个的例子说明浏览器的地址栏可以解析的地址,但是却不符合 RFC 规范。

(?::(d+))?

Regex:
((ftp|http|https)://)?(w+:{0,1}w*@)?(S+)(:[0-9]+)?(/|/([w#!:.?+=&%@!-/]))?

这个可选的因子匹配端口号,它是由一个前置 :
加上一个或多个数字而组成的序列。d表示一个数字字符。一个或多个数字组成的数字串会被捕获型分组4捕获。

经过各种浏览器和多场景的兼容,我们终于得到最后的正则:

(?:/([^?#]*))?