urllib

文章目录

Urllib模块

实现网络爬虫的爬取工作时,就必须使用到网络请求,只有进行了网络请求才可以对响应结果中的数据进行提取。

Urllib模块是Python自带的网络请求模块,无需安装,导入即可使用。

1、Urllib简介

Python3中的Urllib模块中包含多个功能的子模块

➢ urllib.request :用于实现基本HTTP请求的模块。

➢ urllib.error :异常处理模块,如果在发送网络请求时出现了错误,可以捕获 异常进行异常的有效处理。

➢ urllib.parse :用于解析URL的模块。

➢ urllib.robotparser :用于解析robots.txt文件,判断网站是否可以爬取信息。

2、使用urlopen()方法发送请求

urllib.request模块提供了urlopen()方法,用于实现最基本的HTTP请求,接收服务 器所返回的响应数据。

urlopen()方法的语法格式如下:

 urllib.request.urlopen(url, data=None, [timeout]*, cafile=None, capath=None,cadefault=False, context=None)

➢ url:需要访问网站URL完整地址。

➢ data :该参数默认为None,通过该参数确认请求方式,如果是None,表示请求方式 为GET,否则请求方式为POST,在发送POST请求时,参数data需要以字典形式的数 据作为参数值,并且需要将字典类型的参数值转换为字节类型的数据才可以实现 POST请求。

➢ timeout:以秒为单位,设置超时。

➢ cafile、capath :指定一组HTTPS请求受信任的CA证书,cafile指定包含CA证 书的单个文件,capath指定证书文件的目录。

➢ cadefault:CA证书默认值。

➢ context:描述SSL选项的实例。

2.1发送GET请求

在使用urlopen()方法实现一个网络请求时,返回的是一个 “http.client.HTTPResponse”对象。

HTTPResponse常用的方法和属性

import urllib.request # 导入request子模块
url = 'https://www.python.org/'
response = urllib.request.urlopen(url=url) # 发送网络请求
print('响应状态码为:', response.status)
print('响应头所有信息为:', response.getheaders())
print('响应头指定信息为:', response.getheader('Accept-Ranges'))
# 读取HTML代码并进行utf-8解码
print('Python官网HTML代码如下:\n', response.read().decode('utf-8'))

2.2 发送POST请求

urlopen()方法在默认情况下发送的是GET请求,如果需要发送POST请求, 可以为其设置data参数,该参数是bytes类型,所以需要使用bytes方法将参数值进行数据类型的转换。

使用urlopen()方法发送POST请求:

import urllib.request # 导入urllib.request模块
import urllib.parse # 导入urllib.parse模块
url = 'https://www.httpbin.org/post' # post请求测试地址
# 将表单数据转换为bytes类型,并设置编码方式为utf-8
data = bytes(urllib.parse.urlencode({'hello': 'python'}), encoding='utf-8')
response = urllib.request.urlopen(url=url, data=data) # 发送网络请求
print(response.read().decode('utf-8')) # 读取HTML代码并进行

2.3 设置网络超时

urlopen()方法中的timeout参数,用于设置请求超时,该参数以秒为单位,表示如果在请求时,超出了设置的时间还没得到响应时就抛出异常。

response = urllib.request.urlopen(url=url, timeout=0.1)

根据网络环境的不同,可以将超时时间设置为一个合理的时间,如2秒、3秒

捕获超时异常处理网络超时(代码示例):

import urllib.request # 导入urllib.request模块
import urllib.error # 导入urllib.error模块
import socket # 导入socket模块
url = 'https://www.python.org/' # 请求地址
try:
# 发送网络请求,设置超时时间为0.1秒
response = urllib.request.urlopen(url=url, timeout=0.1)
print(response.read().decode('utf-8')) # 读取HTML代码并进行utf-8解码
except urllib.error.URLError as error: # 处理异常
if isinstance(error.reason, socket.timeout): # 判断异常是否为超时异常
print('当前任务已超时,即将执行下一任务!')

3、复杂的网络请求

如果要构建一个完整的网络请求,还需要在请求中添加Headers、Cookies以及代 理IP等内容,这样才能更好的模拟一个浏览器所发送的网络请求。

Request类可以构建一个多种功能的请求对象,其语法格式如下:

–> urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

➢ url:需要访问网站URL完整地址。

➢ data :该参数默认为None,通过该参数确认请求方式,如果是None,表示请求方式 为GET,否则请求方式为POST,在发送POST请求时,参数data需要以字典形式的数 据作为参数值,并且需要将字典类型的参数值转换为字节类型 的数据才可以实现 POST请求。

➢ headers:设置请求头部信息,该参数为字典类型。添加请求头部信息最常见 的用法就是修改User-Agent来伪装成浏览器。

➢ origin_req_host :用于设置请求方的host名称或者是IP。

➢ unverifiable:用于设置网页是否需要验证,默认是False。

➢ method:用于设置请求方式,如GET、POST等,默认为GET请求。

3.1设置请求头

<使用urlopen()方法发送网络请求时,其本身并没有设置请求头参数>

所以在设置请求头信息前,需要在浏览器中找到一个有效的请求头信息,步骤如下:

1.先从浏览器设置中找到开发者工具

2.标签栏选择network

3.在name栏里面找到对应的网站域名

4.选择Headers

5.选到user—agent(将其复制粘贴出来即可)

示例:

import urllib.request # 导入urllib.request模块
import urllib.parse # 导入urllib.parse模块
url = 'https://www.httpbin.org/post' # 请求地址
# 定义请求头信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'}
# 将表单数据转换为bytes类型,并设置编码方式为utf-8
data = bytes(urllib.parse.urlencode({'hello':'python'}), encoding='utf-8')
# 创建Request对象
r = urllib.request.Request(url=url, data=data, headers=headers, method='POST')
response = urllib.request.urlopen(r) # 发送网络请求
print(response.read().decode('utf-8')) # 读取HTML代码并进行utf-8解码

3.2 Cookies的获取与设置

Cookie是服务器向客户端返回响应数据时所留下的标记,当客户端再次访问服务器时将携带这个标记。经过服务器核对后便可以确认当前用户已经登录过,此时可以直接将登录后的数据返回。

在使用爬虫获取网页登录后的数据时,除了使用模拟登录以外,还可以 获取登录后的Cookie,然后利用这个Cookie再次发送请求时,就能以登录 用户的身份获取数据。

Cookies的获取:自行百度,方法很多。

代码示例:

1.发送POST请求实现网页的模拟登录
import urllib.request # 导入urllib.request模块
import urllib.parse # 导入urllib.parse模块
url = 'http://site2.rjkflm.com:666/index/index/chklogin.html' # 登录请求地址
# 将表单数据转换为bytes类型,并设置编码方式为utf-8
data = bytes(urllib.parse.urlencode({'username': 'mrisoft', 'password': 'mrisoft'}),
encoding='utf-8')
# 创建Request对象
r = urllib.request.Request(url=url, data=data, method='POST')
response = urllib.request.urlopen(r) # 发送网络请求
print(response.read().decode('utf-8')) # 读取HTML代码并进行
2.实现在模拟登录过程中获取Cookie信息
import urllib.request # 导入urllib.request模块
import urllib.parse # 导入urllib.parse模块
import http.cookiejar # 导入http.cookiejar子模块
import json # 导入json模块
url = 'http://site2.rjkflm.com:666/index/index/chklogin.html' # 登录请求地址
# 将表单数据转换为bytes类型,并设置编码方式为utf-8
data = bytes(urllib.parse.urlencode({'username': 'mrisoft', 'password': 'mrisoft'}), encoding='utf-8')
cookie = http.cookiejar.CookieJar() # 创建CookieJar对象
cookie_processor = urllib.request.HTTPCookieProcessor(cookie) # 生成cookie处理器
opener = urllib.request.build_opener(cookie_processor) # 创建opener
response = opener.open(url, data=data) # 发送登录请求
response = json.loads(response.read().decode('utf-8'))['msg']
if response == '登录成功!':
for i in cookie: # 循环遍历cookie内容
print(i.name+'='+i.value)

除了简单的获取登录后的Cookie信息以外,还可以将Cookie信息保存为指定的文件格式,在下次登录时直接读取文件中的Cookie信息即可。

有了Cookie文件,使用cookie.load()方法来读取本地的Cookie文件,然后再次向登录后的页面发送给请求。

3.(代码示例)将Cookie信息保存为LWP格式的文件:
import urllib.request # 导入urllib.request模块
import urllib.parse # 导入urllib.parse模块
import http.cookiejar # 导入http.cookiejar子模块
import json # 导入json模块
url = 'http://site2.rjkflm.com:666/index/index/chklogin.html' # 登录请求地址
# 将表单数据转换为bytes类型,并设置编码方式为utf-8
data = bytes(urllib.parse.urlencode({'username': 'mrisoft'
, 'password': 'mrisoft'}), encoding='utf-8')
cookie_file = 'cookie.txt' # 保存cookie文件
cookie = http.cookiejar.LWPCookieJar(cookie_file) # 创建LWPCookieJar对象
# 生成cookie处理器
cookie_processor = urllib.request.HTTPCookieProcessor(cookie)
# 创建opener对象
opener = urllib.request.build_opener(cookie_processor)
response = opener.open(url, data=data) # 发送网络请求
response = json.loads(response.read().decode('utf-8'))['msg']
if response=='登录成功!':
cookie.save(ignore_discard=True, ignore_expires=True) # 保存Cookie文件
4.(代码示例)使用Cookie信息登录并获取页面的信息:
import urllib.request # 导入urllib.request模块
import http.cookiejar # 导入http.cookiejar子模块
# 登录后页面的请求地址
url = 'http://site2.rjkflm.com:666/index/index/index.html'
cookie_file = 'cookie.txt' # cookie文件
cookie = http.cookiejar.LWPCookieJar() # 创建LWPCookieJar对象
# 读取cookie文件内容
cookie.load(cookie_file,ignore_expires=True,ignore_discard=True)
# 生成cookie处理器
handler = urllib.request.HTTPCookieProcessor(cookie)
# 创建opener对象
opener = urllib.request.build_opener(handler)
response = opener.open(url) # 发送网络请求
print(response.read().decode('utf-8')) # 打印登录后页面的html代码

3.3 设置代理IP

使用Urilib模块设置代理IP比较简单,首先需要创建proxy_handler对象,其参数为字典类型的代理IP,键名为协议类型(如HTTP或HTTPS),值为代理链接。 然后利用proxy_handler对象与build_opener()方法构建一个新的opener对象,最后再发送网络请求即可。

示范:使用Urilib模块设置代理IP

import urllib.request # 导入urllib.request模块
url = 'https://www.httpbin.org/get' # 网络请求地址
# 创建代理IP
proxy_handler = urllib.request.ProxyHandler({'https': '58.220.95.114:10053'})
# 创建opener对象
opener = urllib.request.build_opener(proxy_handler)
response = opener.open(url, timeout=2) # 发送网络请求
print(response.read().decode('utf-8')) # 打印返回内容

4. 异常处理

在实现网络请求时,可能会出现很多异常错误,Urllib模块中的urllib.error子模块,包 含了URLError与HTTPError两个比较重要的异常类

URLError类

在URLError类中提供了一个reason属性,可以通过这个属性了解出现异常的错误原因。 例如向一个根本不存在的网络地址发送请求,然后调用reason属性查看错误原因。

(代码示例)调用reason属性处理URLError异常
import urllib.request # 导入urllib.request模块
import urllib.error # 导入urllib.error模块
try:
# 向不存在的网络地址发送请求
response = urllib.request.urlopen('http://site2.rjkflm.com:666/123index.html')
except urllib.error.URLError as error: # 捕获异常信息
print(error.reason) # 打印异常原因

HTTPError类

HTTPError类是URLError类的子类,主要用于处理HTTP请求所出现的异常,该类有以下三个属性

➢ Code:返回HTTP状态码

➢ Reason:返回错误原因。

➢ Headers:返回请求头

(代码示范)使用HTTPError类捕获异常
import urllib.request # 导入urllib.request模块
import urllib.error # 导入urllib.error模块
try:
# 向不存在的网络地址发送请求
response = urllib.request.urlopen('http://site2.rjkflm.com:666/123index.html')
print(response.status)
except urllib.error.HTTPError as error: # 捕获异常信息
print('状态码为:',error.code) # 打印状态码
print('异常信息为:',error.reason) # 打印异常原因
print('请求头信息如下:\n',error.headers) # 打印请求头

由于HTTPError是URLError的子类,有时HTTPError会有捕获不到的异常,所以可以先捕获HTTPError的异常,然后再去捕获父类URLError 的异常,这样可以起到双重保险的作用。

(代码示例)双重异常的捕获
import urllib.request # 导入urllib.request模块
import urllib.error # 导入urllib.error模块
try:
# 向不存在的网络地址发送请求
response = urllib.request.urlopen('https://www.python.org/',timeout=0.1)
except urllib.error.HTTPError as error: # HTTPError捕获异常信息
print('状态码为:',error.code) # 打印状态码
print('HTTPError异常信息为:',error.reason) # 打印异常原因
print('请求头信息如下:\n',error.headers) # 打印请求头
except urllib.error.URLError as error: # URLError捕获异常信息
print('URLError异常信息为:',error.reason)

5.解析链接

Urllib模块中提供了parse子模块,主要用于解析URL,可以实现URL的拆分或者 是组合。

支持多种协议的URL处理。

5.1 拆分URL —— urlparse()方法

parse子模块中提供了urlparse()方法,用于实现URL分解成不同部分,其语法格式如下:

urllib.parse.urlparse(urlstring, scheme=‘’, allow_fragments=True)

➢ urlstring:需要拆分的URL,该参数为必选参数。

➢ scheme :可选参数,表示需要设置的默认协议。如果需要拆分的URL中没有 协议,可以通过该参数设置一个默认的协议,该参数的默认值为空字符串。

➢ allow_fragments :可选参数,如果该参数设置为False,表示忽略fragment这 部分内容,默认为True。

(代码示例)使用urlparse()方法拆分URL:
import urllib.parse #导入urllib.parse模块
parse_result = urllib.parse.urlparse('https://docs.python.org/3/library/urllib.parse.html')
print(type(parse_result)) # 打印类型
print(parse_result) # 打印拆分后的结果

5.2 拆分URL —— urlsplit()方法

urlsplit()方法与urlparse()方法类似,只是urlsplit()方法不再单独拆分params这部 分内容,而是将params合并到path当中,所以返回的结果中只有5部分内容,并且返回的数据类型为SplitResult。

(代码示例)使用urlsplit()方法拆分URL
import urllib.parse #导入urllib.parse模块
# 需要拆分的URL
url = 'https://docs.python.org/3/library/urllib.parse.html'
print(urllib.parse.urlsplit(url)) # 使用urlsplit()方法拆分URL
print(urllib.parse.urlparse(url)) # 使用urlparse()方法拆分URL

5.3 组合URL —— urlunparse()方法

parse子模块中提供了拆分URL的方法,同样也提供了一个urlunparse()方 法实现URL的组合,其语法格式如下:

urllib.parse.urlunparse(parts)

➢ parts:表示用于组合URL的可迭代对象。

注意:使用urlunparse()方法组合URL时,可迭代参数中的元素个数必须是 6个,否则将出现参数元素不足的错误。

(代码示例)使用urlunparse()方法组合URL
import urllib.parse #导入urllib.parse模块
list_url = ['https','docs.python.org','/3/library/urllib.parse.html','','','']
tuple_url = ('https','docs.python.org','/3/library/urllib.parse.html','','','')
dict_url ={'scheme':'https','netloc':'docs.python.org','path':'/3/library/urllib.parse.html','params':'','query':'','fragment':''}
print('组合列表类型的URL:',urllib.parse.urlunparse(list_url))
print('组合元组类型的URL:',urllib.parse.urlunparse(tuple_url))
print('组合字典类型的URL:',urllib.parse.urlunparse(dict_url.values()))

5.4 组合URL —— urlunsplit()方法

urlunsplit()方法与urlunparse()方法类似,只是参数中的元素个数是5个

(代码示例)使用urlunsplit()方法组合URL
import urllib.parse #导入urllib.parse模块
list_url = ['https','docs.python.org','/3/library/urllib.parse.html','','']
tuple_url = ('https','docs.python.org','/3/library/urllib.parse.html','','')
dict_url =
{'scheme':'https','netloc':'docs.python.org','path':'/3/library/urllib.parse.html','query':'','fragment':''}
print('组合列表类型的URL:',urllib.parse.urlunsplit(list_url))
print('组合元组类型的URL:',urllib.parse.urlunsplit(tuple_url))
print('组合字典类型的URL:',urllib.parse.urlunsplit(dict_url.values()))

5.5 连接URL——urljoin()

urlunsplit()方法与urlunparse()方法可以实现URL的组合,parse子模块 还提供了一个urljoin()方法来实现URL的连接,其语法格式如下

urllib.parse.urljoin(base, url, allow_fragments=True)

➢ base:表示基础链接。

➢ url :表示新的链接。

➢ allow_fragments :可选参数,如果该参数设置为False,表示忽略fragment这 部分内容,默认为True。

urljoin()方法在实现URL连接时,base参数只可以设置scheme、netloc以及path三 部分内容,如果第二个参数(url)是一个不完整的URL,那么第二个参数的值 会添加至第一个参数(base)的后面,并自动添加斜杠(/)。如果第二个参数 (url)是一个完整URL,将直接返回第二个参数所对应的值。

(代码示例)使用urljoin()方法连接URL
import urllib.parse #导入urllib.parse模块
base_url = 'https://docs.python.org' # 定义基础链接
# 第二参数不完整时
print(urllib.parse.urljoin(base_url,'3/library/urllib.parse.html'))
# 第二参数完成时,直接返回第二参数的链接
print(urllib.parse.urljoin(base_url,'https://docs.python.org/3/library/urllib.parse.html#urlparsing'))

5.6 URL的编码和解码——urlencode()方法

URL编码是GET请求中比较常见的,将请求中的参数进行编码,尤其是对于中文参数。

parse子模块提供了urlencode()方法与quote()方法用于实现URL编码,而quote()方 法也可以实现对加密后的URL进行解码的操作。

urlencode()方法接收一个字典类型的值,所以要想将URL进行编码需要先将请 求参数定义为字典类型,然后再调用urlencode()方法进行请求参数的编码。

(代码演示)使用urlencode()方法编码请求参数
import urllib.parse #导入urllib.parse模块
base_url = 'http://httpbin.org/get?' # 定义基础链接
params = {'name':'Jack','country':'中国','age':30} # 定义字典类型的请求参数
url = base_url+urllib.parse.urlencode(params) # 连接请求地址
print('编码后的请求地址为:',url)

5.7 URL的编码和解码 —— quote()方法

quote()方法与urlencode()方法所实现的功能类似,但是urlencode()方法只接收字典类型参数,而quote()方法则可以将一个字符串进行编码。

(代码示例)使用quote()方法编码字符串参数
import urllib.parse #导入urllib.parse模块
base_url = 'http://httpbin.org/get?country=' # 定义基础链接
url = base_url+urllib.parse.quote('中国') # 字符串编码
print('编码后的请求地址为:',url)

5.8 URL的编码和解码 —— unquote()方法

unquote()方法可以将编码后的URL字符串逆向解码,无论是通过urlencode()方法 或者是quote()方法所编码的URL字符串都可以使用unquote()方法进行解码。

(代码示例)使用unquote()方法解码请求参数
import urllib.parse #导入urllib.parse模块
u = urllib.parse.urlencode({'country':'中国'}) # 使用urlencode编码
q=urllib.parse.quote('country=中国') # 使用quote编码
print('urlencode编码后结果为:',u)
print('quote编码后结果为:',q)
print('对urlencode解码:',urllib.parse.unquote(u))
print('对quote解码:',urllib.parse.unquote(q))

5.9 URL参数的转换

5.9.1—— parse_qs()方法

请求地址的URL是一个字符串,如果需要将其中的参数转换为字典类型,可以 先使用urlsplit()方法拆分URL,然后再调用query属性获取URL中的参数,最后 使用parse_qs()方法将参数转换为字典类型的数据

(代码示例) 使用parse_qs()方法将参数转换为字典类型

import urllib.parse #导入urllib.parse模块
# 定义一个请求地址
url = 'http://httpbin.org/get?name=Jack&country=%E4%B8%AD%E5%9B%BD&age=30'
q = urllib.parse.urlsplit(url).query # 获取需要的参数
q_dict = urllib.parse.parse_qs(q) # 将参数转换为字典类型的数据
print('数据类型为:',type(q_dict))
print('转换后的数据:',q_dict)
5.9.2——URL参数的转换 —— parse_qsl()方法

parse_qsl()方法也可以将URL参数进行转换,不过parse_qsl()方法会将字符串参 数转换为元组所组成的列表。

(代码示例)使用parse_qsl()方法将参数转换为列表

import urllib.parse #导入urllib.parse模块
str_params = 'name=Jack&country=%E4%B8%AD%E5%9B%BD&age=30' # 字符串参数
list_params = urllib.parse.parse_qsl(str_params) # 将字符串参数转为元组所组成的列表
print('数据类型为:',type(list_params))
print('转换后的数据:',list_params)
  • 12
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值