您的位置:首页 > 运维架构 > Linux

使用 Python 的 urlliib.parse 库解析 URL | Linux 中国

2018-02-23 00:00 1296 查看

Python 中的 urllib.parse 模块提供了很多解析和组建 URL 的函数。-- Darksun

有用的原文链接请访问文末的“原文链接”获得可点击的文内链接、全尺寸原图和相关文章。

致谢转载自 | https://github.com/lujun9972/lujun9972.github.com/blob/source/%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%97%85/%E4%BD%BF%E7%94%A8urlliib.parse%E5%BA%93%E8%A7%A3%E6%9E%90url.org
 作者 | DarksunPython 中的 
urllib.parse
 模块提供了很多解析和组建 URL 的函数。解析url
urlparse()
 函数可以将 URL 解析成 
ParseResult
 对象。对象中包含了六个元素,分别为:◈ 协议(scheme)◈ 域名(netloc)◈ 路径(path)◈ 路径参数(params)◈ 查询参数(query)◈ 片段(fragment)
from urllib.parse import urlparse




url='http://user:pwd@domain:80/path;params?query=queryarg#fragment'




parsed_result=urlparse(url)




print('parsed_result 包含了',len(parsed_result),'个元素')


print(parsed_result)


结果为:
parsed_result 包含了 6 个元素


ParseResult(scheme='http', netloc='user:pwd@domain:80', path='/path', params='params', query='query=queryarg', fragment='fragment')


ParseResult
 继承于 
namedtuple
,因此可以同时通过索引和命名属性来获取 URL 中各部分的值。为了方便起见, 
ParseResult
 还提供了 
username
、 
password
、 
hostname
、 
port
 对 
netloc
 进一步进行拆分。
print('scheme  :', parsed_result.scheme)


print('netloc  :', parsed_result.netloc)


print('path    :', parsed_result.path)


print('params  :', parsed_result.params)


print('query   :', parsed_result.query)


print('fragment:', parsed_result.fragment)


print('username:', parsed_result.username)


print('password:', parsed_result.password)


print('hostname:', parsed_result.hostname)


print('port    :', parsed_result.port)


结果为:
scheme  : http


netloc  : user:pwd@domain:80


path    : /path


params  : params


query   : query=queryarg


fragment: fragment


username: user


password: pwd


hostname: domain


port    : 80


除了 
urlparse()
 之外,还有一个类似的 
urlsplit()
 函数也能对 URL 进行拆分,所不同的是, 
urlsplit()
 并不会把 
路径参数(params)
 从 
路径(path)
 中分离出来。当 URL 中路径部分包含多个参数时,使用 
urlparse()
 解析是有问题的:
url='http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment'




parsed_result=urlparse(url)




print(parsed_result)


print('parsed.path    :', parsed_result.path)


print('parsed.params  :', parsed_result.params)


结果为:
ParseResult(scheme='http', netloc='user:pwd@domain:80', path='/path1;params1/path2', params='params2', query='query=queryarg', fragment='fragment')


parsed.path    : /path1;params1/path2


parsed.params  : params2


这时可以使用 
urlsplit()
 来解析:
from urllib.parse import urlsplit


split_result=urlsplit(url)




print(split_result)


print('split.path    :', split_result.path)


# SplitResult 没有 params 属性


结果为:
SplitResult(scheme='http', netloc='user:pwd@domain:80', path='/path1;params1/path2;params2', query='query=queryarg', fragment='fragment')


split.path    : /path1;params1/path2;params2


若只是要将 URL 后的 
fragment
 标识拆分出来,可以使用 
urldefrag()
 函数:
from urllib.parse import urldefrag




url = 'http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment'




d = urldefrag(url)


print(d)


print('url     :', d.url)


print('fragment:', d.fragment)


结果为:
DefragResult(url='http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg', fragment='fragment')


url     : http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg[/code] 
fragment: fragment


组建URL
ParsedResult
 对象和 
SplitResult
 对象都有一个 
geturl()
 方法,可以返回一个完整的 URL 字符串。
print(parsed_result.geturl())


print(split_result.geturl())


结果为:
http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment


http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment


但是 
geturl()
 只在 
ParsedResult
 和 
SplitResult
 对象中有,若想将一个普通的元组组成 URL,则需要使用 
urlunparse()
 函数:
from urllib.parse import urlunparse


url_compos = ('http', 'user:pwd@domain:80', '/path1;params1/path2', 'params2', 'query=queryarg', 'fragment')


print(urlunparse(url_compos))


结果为:
http://user:pwd@domain:80/path1;params1/path2;params2?query=queryarg#fragment


相对路径转换绝对路径除此之外,
urllib.parse
 还提供了一个 
urljoin()
 函数,来将相对路径转换成绝对路径的 URL。
from urllib.parse import urljoin




print(urljoin('http://www.example.com/path/file.html', 'anotherfile.html'))


print(urljoin('http://www.example.com/path/', 'anotherfile.html'))


print(urljoin('http://www.example.com/path/file.html', '../anotherfile.html'))


print(urljoin('http://www.example.com/path/file.html', '/anotherfile.html'))


结果为:
http://www.example.com/path/anotherfile.html


http://www.example.com/path/anotherfile.html


http://www.example.com/anotherfile.html


http://www.example.com/anotherfile.html


查询参数的构造和解析使用 
urlencode()
 函数可以将一个 dict 转换成合法的查询参数:
from urllib.parse import urlencode




query_args = {


   'name': 'dark sun',


   'country': '中国'


}




query_args = urlencode(query_args)


print(query_args)


结果为:
name=dark+sun&country=%E4%B8%AD%E5%9B%BD


可以看到特殊字符也被正确地转义了。相对的,可以使用 
parse_qs()
 来将查询参数解析成 dict。
from urllib.parse import parse_qs


print(parse_qs(query_args))


结果为:
{'name': ['dark sun'], 'country': ['中国']}


如果只是希望对特殊字符进行转义,那么可以使用 
quote
 或 
quote_plus
 函数,其中 
quote_plus
 比 
quote
 更激进一些,会把 
:
/
 一类的符号也给转义了。
from urllib.parse import quote, quote_plus, urlencode




url = 'http://localhost:1080/~hello!/'


print('urlencode :', urlencode({'url': url}))


print('quote     :', quote(url))


print('quote_plus:', quote_plus(url))


结果为:
urlencode : url=http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F


quote     : http%3A//localhost%3A1080/%7Ehello%21/


quote_plus: http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F


可以看到 
urlencode
 中应该是调用 
quote_plus
 来进行转义的。逆向操作则使用 
unquote
 或 
unquote_plus
 函数:
from urllib.parse import unquote, unquote_plus




encoded_url = 'http%3A%2F%2Flocalhost%3A1080%2F%7Ehello%21%2F'


print(unquote(encoded_url))


print(unquote_plus(encoded_url))


结果为:
http://localhost:1080/~hello!/


http://localhost:1080/~hello!/


你会发现 
unquote
 函数居然能正确地将 
quote_plus
 的结果转换回来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: