uri提取正则表达式

uri的格式多种多样,经常需要校验uri或者分析uri提取各部分,下面提供一个自己写的正则表达式来提取uri,我用它来分析扫描器中输入的或者爬取到的uri,优先提取,由于水平有限,未能完全校验uri是否合法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
url_parse_re = r"^(\w*):\/\/(?:([^:]*)?(?::(.*))?@)?([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$"
"""
^(\w*):\/\/
(?: ([^:]*)?(?::(.*))? @)?
([0-9.\-A-Za-z]+)
(?::(\d+))?
(?:\/([^?#]*))?
(?:\?([^#]*))?
(?:#(.*))?$
"""
testcase = "protocol://username:password@www.sample.com:80/path.php?id=1#hash"
r = re.compile(url_parse_re)
str = re.match(r, testcase)
if str != None:
for x in range(9):
print x, str.group(x)

下面是简略分析:

  • ?:不捕获匹配文本,也不给它分配组和组号
  • ^(\w*):\/\/:匹配protocol://,例如http://,ftp://
  • (?: ([^:]*)?(?::(.*))? @)?匹配用户名密码部分
  • ([0-9.\-A-Za-z]+):匹配hostname部分
  • (?::(\d+))?: 匹配端口
  • (?:\/([^?#]*))?匹配路径
  • (?:\?([^#]*))?匹配请求参数
  • (?:#(.*))?$匹配锚点

    优点是对于不同的uri,各部分所在的group下标不变。例如group(4)是hostname,那么不管uri包不包含username和password,group(4)始终是hostname。