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'

Python 的 urllib.parse 库解析 URL的更多相关文章

  1. Python爬虫入门:Urllib parse库使用详解(二)

    文字转载:https://www.jianshu.com/p/e4a9e64082ef,转载内容仅供学习 如有侵权,请联系删除 获取url参数 urlparse 和 parse_qs ParseRes ...

  2. 通过python的urllib.request库来爬取一只猫

    我们实验的网站很简单,就是一个关于猫的图片的网站:http://placekitten.com 代码如下: import urllib.request respond = urllib.request ...

  3. python中 urllib, urllib2, httplib, httplib2 几个库的区别

    转载 摘要: 只用 python3, 只用 urllib 若只使用python3.X, 下面可以不看了, 记住有个urllib的库就行了 python2.X 有这些库名可用: urllib, urll ...

  4. python中urllib, urllib2,urllib3, httplib,httplib2, request的区别

    permike原文python中urllib, urllib2,urllib3, httplib,httplib2, request的区别 若只使用python3.X, 下面可以不看了, 记住有个ur ...

  5. python爬虫基础02-urllib库

    Python网络请求urllib和urllib3详解 urllib是Python中请求url连接的官方标准库,在Python2中主要为urllib和urllib2,在Python3中整合成了urlli ...

  6. URL组成成分及各部分作用简介及urllib.parse / uri

    URL的一般格式为(带方括号[]的为可选项): protocol :// hostname[:port] / path / [;parameters][?query]#fragment urllib. ...

  7. python爬虫 urllib模块url编码处理

    案例:爬取使用搜狗根据指定词条搜索到的页面数据(例如爬取词条为‘周杰伦'的页面数据) import urllib.request # 1.指定url url = 'https://www.sogou. ...

  8. Python爬虫之urllib.parse详解

    Python爬虫之urllib.parse 转载地址 Python 中的 urllib.parse 模块提供了很多解析和组建 URL 的函数. 解析url 解析url( urlparse() ) ur ...

  9. urllib.parse解析链接

    1. urlparse() 解析链接,注意,返回值比3多一个params的属性 from urllib.parse import urlparse result = urlparse('http:// ...

随机推荐

  1. 安卓学习笔记一 Activity延迟转跳实现欢迎界面

    新人学习安卓,为了刚好的学习,现做如下笔记..同时希望自己的经验可以帮助新人们学习入门. 几乎每个app都有个欢迎界面,我们可以使用Activity转跳来实现. 首先建立一个MainActivity ...

  2. Hadoop基本知识,(以及MR编程原理)

     hadoop核心是:MapReduce和HDFS (对应着job执行(程序)和文件存储系统(数据的输入和输出)) CRC32作数据交验:在文件Block写入的时候除了写入数据还会写入交验信息,在读取 ...

  3. mahout系列之---谱聚类

    1.构造亲和矩阵W 2.构造度矩阵D 3.拉普拉斯矩阵L 4.计算L矩阵的第二小特征值(谱)对应的特征向量Fiedler 向量 5.以Fiedler向量作为kmean聚类的初始中心,用kmeans聚类 ...

  4. rails小重构:将图片加入产品Model之二

    在前面我们重构了product中图片的实现,但是还是有一些小问题.比如用户如果上传一个非图片格式的文件时的验证情况. 我们之前是将图片格式验证代码放在Picture类中: validates_form ...

  5. ethtool确定网卡对应的物理网口

    在配置有多个网络接口的设备时我们会犯难,eth0.eth1.--到底是那个接口? 我使用的机器是CentOS系统,打开终端,输入ethtool –help 显示帮助信息,下面我就简要介绍一下最常用的两 ...

  6. Html5深受欢迎的理由

    一.世界知名浏览器厂商对Html5的支持 微软:2010年微软称完成Ie9的开发后,讲更对支持css3.svg和html5等互联网浏览通用标准. Google:2010年谷歌重点开发html5项目. ...

  7. Day19 Django

    老师代码博客: http://www.cnblogs.com/yuanchenqi/articles/7552333.html 上节内容回顾: class Book(models.Model): ti ...

  8. “Location of the Android SDK has not been set up in the preferences”问题的解决

    方法来源:http://stackoverflow.com/questions/5894929/location-of-the-Android-sdk-has-not-been-setup-in-th ...

  9. hadoop 2.x 简单实现wordCount

    简单实现hadoop程序,包括:hadoop2.x的实现写法 import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs ...

  10. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (二)

    上次讲解了FairyGUI的最简单的热更新办法,并对其中一个Demo进行了修改并做成了热更新的方式. 这次我们来一个更加复杂一些的情况:Emoji. FairyGUI的   Example 04 - ...