Python 的 urllib.parse 库解析 URL
Python 中的 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
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 的结果转换回来。
1、获取url参数
>>>from urllib import parse
>>> url =r'[https://docs.python.org/3.5/search.html?q=parse&check_keywords=yes&area=default](https://docs.python.org/3.5/search.html?q=parse&check_keywords=yes&area=default)'
>>> parseResult=parse.urlparse(url)
>>> parseResult
ParseResult(scheme='https', netloc='docs.python.org', path='/3.5/search.html', params='', query='q=parse&check_keywords=yes&area=default', fragment=' ')
>>> param_dict=parse.parse_qs(parseResult.query)
>>> param_dict
{'q': ['parse'],'check_keywords': ['yes'],'area': ['default']}
>>> q=param_dict['q'][0]
>>> q
'parse'
#注意:加号会被解码,可能有时并不是我们想要的
>>> parse.parse_qs('proxy=183.222.102.178:8080&task=XXXXX|5-3+2')
{'proxy': ['183.222.102.178:8080'],'task': ['XXXXX|5-3 2']}
2、urlencode
>>> from urllib import parse
>>> query = {
'name': 'walker',
'age': 99,
}
>>> parse.urlencode(query)
'name=walker&age=99'
3、quote/quote_plus
>>> from urllib import parse
>>> parse.quote('a&b/c') #未编码斜线
'a%26b/c'
>>> parse.quote_plus('a&b/c') #编码了斜线
'a%26b%2Fc'
4、unquote/unquote_plus
from urllib import parse
>>> parse.unquote('1+2') #不解码加号
'1+2'
>>> parse.unquote_plus('1+2') #把加号解码为空格
'1 2'
参考:http://ju.outofmemory.cn/entry/344949 http://www.jb51.net/article/92818.htm
- WPF/XML 资源及相关开源项目
- Android应用底部导航栏(选项卡)实例
- 有关 ASMX 2.0、WSE 3.0 和 WCF 的内容
- 微信小程序游戏其实一般,我也就站在寒风里玩了一个小时
- beagle MONO 应用的desktop search
- Python3与OpenCV3.3 图像处理(一)-环境搭建与简单DEMO
- winform中利用正则表达式得到有效的电话/手机号
- 浅述RDF,畅想一下FOAF应用
- 数据源控件参数类Parameter
- 我们来继续研究 mybatis 框架sql映射文件的属性
- 开源.NET邮件服务器
- 次次获得《头脑王者》满分的秘诀
- 如何在ASP.NET 2.0中定制Expression Builders
- codeproject 几篇asp.net文章
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 深入浅出mongodb(一)
- 深入浅出mongodb(二)
- 算法——快速排序
- 算法——二分查找算法
- 第一篇——Ubuntu 安装 Elasticsearch
- Ubuntu安装Redis(手动编译)
- 第五节:Activiti6.0——流程定义相关API
- 第四节:Activiti6.0——使用zip、bpmn代码生成流程图的资源部署以及资源的查询
- 第三节:Activiti6.0——Query的API使用
- 第二节:Activiti6.0配置文件的读取
- SpringMvc配置文件上传
- 使用web.xml配置SpringMvc(使用Java加载配置)
- SpringMVC配置字符过滤器的两种方式
- SpringMvc使用Json(Java配置方式)
- 使用IDEA创建SpringMvc并整合Thymeleaf(Java配置版)