小白学 Python 爬虫(14):urllib 基础使用(四)

人生苦短,我用 Python
前文传送门:
小白学 Python 爬虫(2):前置准备(一)基本类库的安装
小白学 Python 爬虫(3):前置准备(二)Linux基础入门
小白学 Python 爬虫(4):前置准备(三)Docker基础入门
小白学 Python 爬虫(6):前置准备(五)爬虫框架的安装
小白学 Python 爬虫(10):Session 和 Cookies
小白学 Python 爬虫(11):urllib 基础使用(一)
小白学 Python 爬虫(12):urllib 基础使用(二)
小白学 Python 爬虫(13):urllib 基础使用(三)
Parse 模块
官方文档:https://docs.python.org/zh-cn/3.7/library/urllib.parse.html
前面我们介绍了 urllib 的 Request 模块和 Error 模块,本篇我们接着介绍 Parse 模块。
先看一下官方文档的解释吧:
This module defines a standard interface to break Uniform Resource Locator (URL) strings up in components (addressing scheme, network location, path etc.), to combine the components back into a URL string, and to convert a "relative URL" to an absolute URL given a "base URL."
The module has been designed to match the Internet RFC on Relative Uniform Resource Locators. It supports the following URL schemes: file, ftp, gopher, hdl, http, https, imap, mailto, mms, news, nntp, prospero, rsync, rtsp, rtspu, sftp, shttp, sip, sips, snews, svn, svn+ssh, telnet, wais, ws, wss.
The urllib.parse module defines functions that fall into two broad categories: URL parsing and URL quoting.
大意是该模块定义了一个处理 URL 的标准接口,主要用于分解 URL 字符串为组件和将组件组合回 URL 字符串,并且可以将相对 URL 转换为绝对 URL 。
它支持的 URL 协议有:file, ftp, gopher, hdl, http, https, imap, mailto, mms, news, nntp, prospero, rsync, rtsp, rtspu, sftp, shttp, sip, sips, snews, svn, svn+ssh, telnet, wais, ws, wss。
urllib.parse 模块定义的函数分为两大类:URL 解析和 URL 引用。
URL 解析
urlparse()
先看最常用的一个方法 urlparse() ,该方法主要用于识别 URL 和将其分段,再来看下 urlparse 对于一个 URL 的定义:
scheme://netloc/path;parameters?query#fragment
可以看到, urlparse() 将一个 URL 拆解成为 6 个部分,分别是 scheme 、 netloc 、 path 、 params 、 query 和 fragment 。
大体上可以看出来,解析时是会有特定的分隔符的。
- scheme:位于
://前面,代表了当前的协议。 - netloc:位于第一个
/之前,代表了域名。 - path:位于第一个
/和;之间,代表了访问路径。 - parameters:位于
;和?之间,代表了路径元素的参数。 - query:位于
?和#之间,代表了查询组件。 - fragment:位于
#之后,代表了片段识别。
一个标准的 URL 应该是由以上部分组成,但是实际上,我们现在看到的大部分的 URL 并不会在链接中包含 ; 。
看个小例子吧,随便在官方文档上找了个连接,我们使用 urlparse() 将它解析一下看下结果:
from urllib.parse import urlparse
result = urlparse('https://docs.python.org/zh-cn/3.7/library/urllib.parse.html#module-urllib.parse')
print(type(result))
print(result)
执行结果:
<class 'urllib.parse.ParseResult'>
ParseResult(scheme='https', netloc='docs.python.org', path='/zh-cn/3.7/library/urllib.parse.html', params='', query='', fragment='module-urllib.parse')
可以看到, urlparse() 返回的数据类型是 urllib.parse.ParseResult 对象,它实际上是一个元组数据类型,而这个元组则包含了我们上面介绍的那些组件元素。
如果我们想要获取这个链接中的某个值怎么获取呢?比如说我们想获取当前这个链接的域名信息:
print(result.netloc)
结果如下:
docs.python.org
我们可以直接通过这个 urllib.parse.ParseResult 对应的属性将它取出来,而 urlparse() 甚至为我们提供了索引的方式来进行取值,对应关系如下表(以下内容来自官方文档):
| 属性 | 索引 | 描述 | 值(如果不存在) |
|---|---|---|---|
| scheme | 0 | URL 方案说明符 | scheme parameter |
| netloc | 1 | 域名 | 空字符串 |
| path | 2 | 分层路径 | 空字符串 |
| params | 3 | 最后路径元素的参数 | 空字符串 |
| query | 4 | 查询组件 | 空字符串 |
| fragment | 5 | 片段识别 | 空字符串 |
我们再通过索引的方式获取一下刚才我们想获取的域名信息:
print(result[1])
结果如下:
docs.python.org
获取成功。
我们再来看一下 urlparse() 的语法:
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
- urlstring:这是必填项,即待解析的URL。
- scheme:它是默认的协议(比如 http 或 https 等)。假如这个链接没有带协议信息,会将这个作为默认的协议。
- allow_fragments:即是否忽略 fragment 。如果它被设置为 False , fragment 部分就会被忽略,它会被解析为 path 、 parameters 或者 query 的一部分,而 fragment 部分为空。
我们再来写一个示例,连接还是使用刚才上面的链接,我们在这个示例中去掉链接中的 scheme 信息,在参数中指定 scheme 信息,并且将 allow_fragments 设置为 False ,看下片段识别将会被解析成哪一部分:
from urllib.parse import urlparse
result1 = urlparse('docs.python.org/zh-cn/3.7/library/urllib.parse.html#module-urllib.parse', scheme = "https", allow_fragments = False)
print(result1)
运行结果如下:
ParseResult(scheme='https', netloc='', path='docs.python.org/zh-cn/3.7/library/urllib.parse.html#module-urllib.parse', params='', query='', fragment='')
可以从结果中看出, scheme 信息是可以正常识别出来的,而片段识别信息则被解析成为了 path 的一部分。
urlunparse()
有了解析链接的 urlparse() ,那么一定会存在构建链接的 urlunparse() 。
这个方法它接受的参数是一个可迭代对象,但是它的长度必须是 6 ,否则会抛出参数数量不足或者过多的问题。
我们还是通过一个示例了解一下:
from urllib.parse import urlparse, urlunparse
params = ('https', 'www.geekdigging.com', 'index.html', 'people', 'a=1', 'geekdigging')
print(urlunparse(params))
这里的参数使用的数据类型是元组,当然也可以选择其他的可迭代的数据类型,例如列表或者特定的数据结构等等。
运行结果如下:
https://www.geekdigging.com/index.html;people?a=1#geekdigging
这样我们就简单的实现了 URL 的构造,如果其中某些参数在构建的时候不存在,切记不可直接不写,留空字符串即可,如下:
params = ('https', 'www.geekdigging.com', 'index.html', '', '', 'geekdigging')
urlsplit()
urlsplit() 这个方法和 urlparse() 非常像,唯一的区别就是 urlsplit() 不再单独解析 params 这个组件,只会返回 5 个组件的结果,它将 params 合并到了 path 中。还是看一个示例:
from urllib.parse import urlsplit
result_urlsplit = urlsplit("https://www.geekdigging.com/index.html;people?a=1#geekdigging")
print(type(result_urlsplit))
print(result_urlsplit)
结果如下:
<class 'urllib.parse.SplitResult'>
SplitResult(scheme='https', netloc='www.geekdigging.com', path='/index.html;people', query='a=1', fragment='geekdigging')
可以发现,返回结果是 urllib.parse.SplitResult ,它其实也是一个元组类型,既可以用属性获取值,也可以用索引来获取。示例如下:
print(result_urlsplit.netloc)
print(result_urlsplit[1])
结果如下:
www.geekdigging.com
www.geekdigging.com
urlunsplit()
看到这个命名各位同学应该大致上已经可以猜出来 urlunsplit() 它的作用以及用法了。
对的,木有错,它和上面介绍的 urlunparse() 是非常相似的,唯一的区别就是它的参数长度必须为 5 。示例如下:
from urllib.parse import urlunsplit
params_urlunsplit = ('https', 'www.geekdigging.com', 'index.html;people', 'a=1', 'geekdigging')
print(urlunsplit(params_urlunsplit))
结果如下:
https://www.geekdigging.com/index.html;people?a=1#geekdigging
其余的不多做介绍,完全参考上面的 urlunparse() 。
urljoin()
上面我们介绍了 urlunparse() 和 urlunsplit() 两个方法可以合成链接,前提是我们需要有定长的参数可迭代对象,链接的每一个组件都要对应的分开。
而 urllib.parase 中提供的 urljoin() 这个方法就比较有意思了。我们先看下官方的解释:
Construct a full ("absolute") URL by combining a "base URL" (base) with another URL (url). Informally, this uses components of the base URL, in particular the addressing scheme, the network location and (part of) the path, to provide missing components in the relative URL.
其中的大意是:通过基础的 URL 和另一个 URL 来完成组合完成最终的 URL ,它会分析基础的 URL 的 scheme 、 netloc 和 path 这三个内容,并对新连接缺失的部分进行补充,完成最终的组合。
有点没看懂?没关系,我们写几个简单的示例就清楚了:
print(urljoin("https://www.geekdigging.com/", "index.html"))
print(urljoin("https://www.geekdigging.com/", "https://www.geekdigging.com/index.html"))
print(urljoin("https://www.geekdigging.com/", "?a=aa"))
print(urljoin("https://www.geekdigging.com/#geekdigging", "https://docs.python.org/zh-cn/3.7/library/urllib.parse.html"))
结果如下:
https://www.geekdigging.com/index.html
https://www.geekdigging.com/index.html
https://www.geekdigging.com/?a=aa
https://docs.python.org/zh-cn/3.7/library/urllib.parse.html
不知各位同学看懂了没?
只有在第二个参数链接缺失 scheme 、 netloc 和 path 这三个内容的时候,才会从第一个参数中获取对应的内容进行组合。
parse_qs()
这个方法可以让我们将一串 GET 请求中的参数转换成为字典。
我们在百度搜索的时候,像百度发送的请求其实是 GET 请求,例如我在百度搜索 Python ,这时浏览器上的链接显示为:https://www.baidu.com/s?ie=UTF-8&wd=python 。这里的 GET请求参数实际上是 ? 后面这部分 ie=UTF-8&wd=python 。我们还是用 parse_qs() 来写个示例看一下:
from urllib.parse import parse_qs
print(parse_qs("ie=UTF-8&wd=python"))
执行结果如下:
{'ie': ['UTF-8'], 'wd': ['python']}
可以看到,参数成功的转换成了字典。
parse_qsl()
还有一个parse_qsl()方法,它用于将参数转化为元组组成的列表,示例如下:
from urllib.parse import parse_qsl
# parse_qsl 示例
print(parse_qsl("ie=UTF-8&wd=python"))
执行结果如下:
[('ie', 'UTF-8'), ('wd', 'python')]
可以看到,参数成功的转换成了元组组成的列表。
URL 引用
urlencode()
我们接着介绍一个比较常用的方法: urlencode() 。
这个方法是用来构造 GET 请求参数的,例如我们上面示例中所使用到的百度搜索的参数,它可以将一个字典转换成为 GET 请求参数。示例如下:
from urllib.parse import urlencode
# urlencode 示例
dict = {
"name": "极客挖掘机",
"age": 18
}
print("https://www.geekdigging.com/" + urlencode(dict))
结果如下:
https://www.geekdigging.com/name=%E6%9E%81%E5%AE%A2%E6%8C%96%E6%8E%98%E6%9C%BA&age=18
执行结果中有一串看不懂是什么的字符串,这个是 URL 编码,因为参数中含有中文参数时,可能会导致乱码,可以看到 urlencode() 这个方法,自动的帮我们对中文进行了 URL 编码。
quote()
这个方法是 urllib.parse 中专门为我们提供的 URL 转码的方法,我们还是拿上面一个示例的中文进行转码,各位同学可以看下结果是否相同:
from urllib.parse import quote
# quote 示例
print(quote("极客挖掘机"))
结果如下:
%E6%9E%81%E5%AE%A2%E6%8C%96%E6%8E%98%E6%9C%BA
好像是一样的对吧,说明我们测试成功。
unquote()
有了 quote() 的方法,当然会搞一个专门逆向的方法咯~~~
我们把刚才经过 URL 编码后的字符串拿出来做测试,看看能不能转回去:
from urllib.parse import unquote
# unquote 示例
print(unquote("%E6%9E%81%E5%AE%A2%E6%8C%96%E6%8E%98%E6%9C%BA"))
结果如下:
极客挖掘机
可以看到,经过我们 URL 编码后的字符串逆向成功。
本篇的内容就到这里了,内容有些又臭又长,不过还是希望各位同学可以亲自动手练习一下。
毕竟,自己不敲代码是永远学不会代码的。
示例代码
本系列的所有代码小编都会放在代码管理仓库 Github 和 Gitee 上,方便大家取用。
参考
https://www.cnblogs.com/zhangxinqi/p/9170312.html
小白学 Python 爬虫(14):urllib 基础使用(四)的更多相关文章
- 小白学 Python 爬虫(15):urllib 基础使用(五)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(11):urllib 基础使用(一)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(12):urllib 基础使用(二)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(13):urllib 基础使用(三)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(16):urllib 实战之爬取妹子图
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(17):Requests 基础使用
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(30):代理基础
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(33):爬虫框架 Scrapy 入门基础(一)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
随机推荐
- 在mac上用parallels创建双windows虚拟机调试windows驱动
先创建两个windows 7 虚拟机,一个装windbg作为调试机,一个被调试 1 调试机 1 先装windbg https://developer.microsoft.com/en-us/windo ...
- how2heap 源码及输出
备个份,慢慢写总结 1 first_fit #include <stdio.h> #include <stdlib.h> #include <string.h> i ...
- vue学习之插槽
插槽 插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性. 个人理解:我感觉插槽就是父组件控制插槽 ...
- [考试反思]0920csp-s模拟测试48:弱小
注:T1全场46个人里42个AC了. %%%zkt也AK了呢越来越强啊 我是真的越来越弱了吗? 我到底在干什么... 在难度递增的题里分数递增... 考试过程大体还好,但是如此快速地WA掉T1也真是蠢 ...
- 地精部落:dp
Description 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi, ...
- Google I/O 大会上提出的UI优化相关
1.ListView的Adapter Adapter在ListView中的工作原理是: 上图也正好反映出ListView使用了Adapter来适配数据源. 每一个Item条目都是通过Adapter.g ...
- WIN7安装Docker Toolbox、制作镜像并发到阿里云
一.安装Docker Toolbox,并配置国内源加速 WIndows7不支持Hyper-v,所以只能采用Docker Toolbox的方式使用Docker.传送门:http://mirrors.al ...
- variable precision SWAR算法
计算二进制形式中1的数量这种问题,在各种刷题网站上比较常见,以往都是选择最笨的遍历方法“蒙混”过关.在了解Redis的过程中接触到了variable precision SWAR算法(以下简称VP-S ...
- HTML 转 PDF 之 wkhtmltopdf
wkhtmltopdf是一个可以把html转为pdf的插件,有windows.linux等平台的版本,比较简单 官网下载 https://wkhtmltopdf.org/downloads.html ...
- 除了获取 MAC 地址还能干啥
以前写过一篇<在Web中获取MAC地址>的文章,文章的地址是:https://www.cnblogs.com/tosser/p/9022187.html,我当时使用 OCX ...