Python之urllib库详解
urllib 是 Python 标准库中⽤于⽹络请求的库。
该库有四个模块,分别是:
<
urllib.parse
1 发起请求
模拟浏览器发起⼀个 HTTP 请求,我们需要⽤到 quest 模块。quest 的作⽤不仅仅是发起请求,还能获取请求返回结果。发起请求,单靠urlopen()⽅法就可以叱咤风云。我们先看下 urlopen() 的 API:
data 是 bytes 类型的内容,可通过 bytes()函数转为化字节流。它也是可选参数。使⽤ data 参数,请求⽅式变成以 POST ⽅式提交表单。使⽤标准格式是application/x-www-form-urlencoded
timeout 参数是⽤于设置请求超时时间。单位是秒。
cafile和capath代表 CA 证书和 CA 证书的路径。如果使⽤HTTPS则需要⽤到。
context参数必须是ssl.SSLContext类型,⽤来指定SSL设置
该⽅法也可以单独传⼊quest.Request对象
该函数返回结果是⼀个http.client.HTTPResponse对象。
使⽤ quest.urlopen() 去请求百度贴吧,并获取到它页⾯的源代码。
quest
url = "tieba.baidu"
response = quest.urlopen(url)
html = ad()        # 获取到页⾯的源代码
print(html.decode('utf-8'))    # 转化为 utf-8 编码
1.2 设置请求超时
有些请求可能因为⽹络原因⽆法得到响应。因此,我们可以⼿动设置超时时间。当请求超时,我们可以采取进⼀步措施,例如选择直接丢弃该请求或者再请求⼀次。
quest
url = "tieba.baidu"
response = quest.urlopen(url, timeout=1)
ad().decode('utf-8'))
1.3 使⽤ data 参数提交数据
在请求某些⽹页时需要携带⼀些数据,我们就需要使⽤到 data 参数。
import urllib.parse
quest
url = "www.baidu/"
params = {
'name':'TTT',
'author':'Miracle'
}
data = bytes(urllib.parse.urlencode(params), encoding='utf8')
response = quest.urlopen(url, data=data)
ad().decode('utf-8'))
params 需要被转码成字节流。⽽ params 是⼀个字典。我们需要使⽤ urllib.parse.urlencode() 将字典转化为字符串。再使⽤ bytes() 转为字节流。最后使⽤ urlopen() 发起请求,请求是模拟⽤ POST ⽅式提交表单数据。
注意:当url地址含有中⽂或者“/”的时候,这是就需要⽤做urlencode⼀下编码转换。urlencode的参数
是词典,它可以将key-value这样的键值对转换成我们想要的格式
1.4 使⽤ Request
由上我们知道利⽤ urlopen() ⽅法可以发起简单的请求。但这⼏个简单的参数并不⾜以构建⼀个完整的请求,如果请求中需要加⼊headers(请求头)、指定请求⽅式等信息,我们就可以利⽤更强⼤的Request类来构建⼀个请求。
按照国际惯例,先看下 Request 的构造⽅法:
unverifiable=False, method=None)
data 参数跟 urlopen() 中的 data 参数⽤法相同。
headers 参数是指定发起的 HTTP 请求的头部信息。headers 是⼀个字典。它除了在 Request 中添加,还可以通过调⽤ Reques t实例的add_header() ⽅法来添加请求头。
origin_req_host 参数指的是请求⽅的 host 名称或者 IP 地址。
unverifiable 表⽰请求是否是⽆法验证的,默认False。意思就是说⽤户没有⾜够权限来选择接收这个请求的结果。例如我们请求⼀个HTML⽂档中的图⽚,但是我们没有⾃动抓取图像的权限,我们就要将 unverifiable 的值设置成 True。
method 参数指的是发起的 HTTP 请求的⽅式,有 GET、POST、DELETE、PUT等
1.4.1 简单使⽤ Request
使⽤ Request 伪装成浏览器发起 HTTP 请求。如果不设置 headers 中的 User-Agent,默认的User-Agent是Python-urllib/3.5。可能⼀些⽹站会将该请求拦截,所以需要伪装成浏览器发起请求。我使⽤的 User-Agent 是 Chrome 浏览器。
#修改User-Agent为chrome的UA进⾏伪装
quest
url = "tieba.baidu/"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
}
request = quest.Request(url=url, headers=headers)
response = quest.urlopen(request)
ad().decode('utf-8'))
1.4.2 Request ⾼级⽤法
如果我们需要在请求中添加代理、处理请求的 Cookies,我们需要⽤到Handler和OpenerDirector。
1) Handler
Handler 的中⽂是处理者、处理器。 Handler 能处理请求(HTTP、HTTPS、FTP等)中的各种事情。它的具体实现是这个类
fault_open()、protocol_request()等。
继承 BaseHandler 有很多个,我就列举⼏个⽐较常见的类:
ProxyHandler:为请求设置代理
HTTPCookieProcessor:处理 HTTP 请求中的 Cookies
HTTPDefaultErrorHandler:处理 HTTP 响应错误。
HTTPRedirectHandler:处理 HTTP 重定向。
HTTPPasswordMgr:⽤于管理密码,它维护了⽤户名密码的表。
HTTPBasicAuthHandler:⽤于登录认证,⼀般和HTTPPasswordMgr结合使⽤。
2) OpenerDirector
对于 OpenerDirector,我们可以称之为 Opener。我们之前⽤过 urlopen() ⽅法,实际上它就是 urllib 为我们提供的⼀个Opener。那 Opener 和 Handler ⼜有什么关系?opener 对象是由 build_opener(handler) ⽅法来创建出来。我们需要创建⾃定义的 opener,就需要使⽤install_opener(o
pener)⽅法。值得注意的是,install_opener 实例化会得到⼀个全局的 OpenerDirector 对象。
1.5 使⽤代理
我们已经了解了 opener 和 handler,接下来我们就通过⽰例来深⼊学习。第⼀个例⼦是为 HTTP 请求设置代理
有些⽹站做了浏览频率限制。如果我们请求该⽹站频率过⾼。该⽹站会被封 IP,禁⽌我们的访问。所以我们需要使⽤代理来突破这“枷锁”。quest
url = "tieba.baidu/"
headers = {
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/56.0.2924.87 Safari/537.36'
}
proxy_handler = quest.ProxyHandler({
'http': 'web-proxy.oa:8080',
'https': 'web-proxy.oa:8080'
})
opener = quest.build_opener(proxy_handler)
request = quest.Request(url=url, headers=headers)
response = quest.urlopen(request)
ad().decode('utf-8'))
1.6 认证登录
有些⽹站需要携带账号和密码进⾏登录之后才能继续浏览⽹页。碰到这样的⽹站,我们需要⽤到认证登录。我们⾸先需要使⽤HTTPPasswordMgrWithDefaultRealm() 实例化⼀个账号密码管理对象;然后使⽤ add_password() 函数添加账号和密码;接着使⽤HTTPBasicAuthHandler() 得到 hander;再使⽤ build_opener() 获取 opener 对象;最后使⽤ opener 的 open() 函数发起请求。
第⼆个例⼦是携带账号和密码请求登录博客园,代码如下:
quest
url = "cnblogs/xtznb/"
user = '奇迹'
password = 'password'
pwdmgr = quest.HTTPPasswordMgrWithDefaultRealm()
pwdmgr.add_password(None,url,user,password)
auth_handler = quest.HTTPBasicAuthHandler(pwdmgr)
opener = quest.build_opener(auth_handler)
response = opener.open(url)
ad().decode('utf-8'))
1.7 Cookies设置
如果请求的页⾯每次需要⾝份验证,我们可以使⽤ Cookies 来⾃动登录,免去重复登录验证的操作。获取 Cookies 需要使⽤
第三个例⼦是获取请求百度贴吧的 Cookies 并保存到⽂件中,代码如下:
kiejar
quest
url = "tieba.baidu/"
fileName = ''
cookie = kiejar.CookieJar()
handler = quest.HTTPCookieProcessor(cookie)
opener = quest.build_opener(handler)
response = opener.open(url)
f = open(fileName,'a')
for item in cookie:
f.write(item.name+" = "+item.value+'\n')
f.close()
1.8 HTTPResponse
从上⾯的例⼦可知,使⽤ quest.urlopen() 或者 opener.open(url) 返回结果是⼀个 http.client.HTTPResponse 对象。它具有 msg、version、status、reason、debuglevel、closed等属性以及read()、readinto()、getheader(name)、getheaders()、fileno()等函数。
2 错误解析
发起请求难免会出现各种异常,我们需要对异常进⾏处理,这样会使得程序⽐较⼈性化。
异常处理主要⽤到两个类,URLError和HTTPError。
URLError
URLError 是 异常类的基类, 可以捕获由quest 产⽣的异常。
它具有⼀个属性reason,即返回错误的原因。
捕获 URL 异常的⽰例代码:
quest
url = "le"
try:
response = request.urlopen(url)
except error.URLError as e:
ason)
HTTPError HTTPError 是 UEKRrror 的⼦类,专门处理 HTTP 和 HTTPS 请求的错误。它具有三个属性。
  1)code:HTTP 请求返回的状态码。
  2)reason:与⽗类⽤法⼀样,表⽰返回错误的原因。
  3)headers`:HTTP 请求返回的响应头信息。
获取 HTTP 异常的⽰例代码, 输出了错误状态码、错误原因、服务器响应头
error parse quest
url = "le"
try:
response = request.urlopen(url)
except error.HTTPError as e:
print('code: ' + e.code + '\n')
print('reason: ' + e.reason + '\n')
print('headers: ' + e.headers + '\n')
sponse
(在使⽤urlopen()⽅法或者opener的open()⽅法发起请求后,获得的结果是⼀个response对象。这个对象有⼀些⽅法和属性,可以让我们对请求返回的结果进⾏⼀些处理。)
geturl()  : 返回获取的真实的URL,这个很有⽤,因为 urlopen(或者 opener 对象使⽤的)或许会有重定向。获取的 URL 或许跟请求 URL 不同。
info() : 这个返回对象的字典对象,该字典描述了获取的页⾯情况。通常是服务器发送的特定头 headers。
read():获取响应返回的数据,只能使⽤⼀次。
getcode():获取服务器返回的状态码。
getheaders():获取返回响应的响应报头。
3.urllib.parse
(urllib.parse是urllib中⽤来解析各种数据格式的模块)
from urllib import parse
keyword = '南北'
parse.quote(keyword)
=======>>'%E5%8D%97%E5%8C%97'
#如果需要将编码后的数据转换回来,可以使⽤unquote()⽅法。
parse.unquote('%E5%8D%97%E5%8C%97')
=======>>'南北'
2. urllib.parse.urlencode
在访问url时,我们常常需要传递很多的url参数,⽽如果⽤字符串的⽅法去拼接url的话,会⽐较⿇烦,所以urllib中提供了urlencode这个⽅法来拼接url参数。
from urllib import parse
params = {'wd': '南北', 'code': '1', 'height': '188'}
parse.urlencode(params)
=======>>'wd=%E5%8D%97%E5%8C%97&code=1&height=188'
在urllib中主要设置了两个异常,⼀个是URLError,⼀个是HTTPError,HTTPError是URLError的⼦类。
HTTPError还包含了三个属性:
code:请求的状态码
reason:错误的原因
headers:响应的报头
import HTTPError
try:
request.urlopen('www.jianshu')
except HTTPError as e:
de)
403
⼀个使⽤代理的例⼦:
proxy_handler = quest.ProxyHandler({'http':
'ample:3128/'})
proxy_auth_handler = quest.ProxyBasicAuth()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
opener = quest.build_opener(proxy_handler, proxy_auth_handler)
opener.open('ample/login.html')
添加HTTP请求头部:
quest
req = quest.Request('ample/')
req.add_header('Referer', '/')
r = quest.urlopen(req)
更改User-agent:
quest
opener = quest.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
opener.open('ample/')
三、Python3.X中使⽤整合后的urllib
Python2.x 有这些库名可⽤: urllib,urllib2,urllib3,httplib,httplib2,requestsPython3.x 有这些库名可⽤:
urllib,urllib3,httplib2,requests
若只使⽤Python3.x,记住有个urllib的库就⾏了。Pyhton2.x和Python3.x都有urllib3和requests, 它们不是标准库。urllib3提供线程安全连接池和⽂件post等⽀持,与urllib及urllib2的关系不⼤。requests ⾃称HTTP for Humans,使⽤更简洁⽅便。
Python3.x中将urllib2合并到了urllib,之后此包分成了以下⼏个模块:
< ⽤于处理前⾯request引起的异常
urllib.parse ⽤于解析URL
Python3.x中,随着urllib2合⼊urllib,⼀些常⽤的⽅法也发⽣了变化:2
在Python2.x中使⽤import urlparse——在Python3.x中会使⽤import urllib.parse
在Python2.x中使⽤urllib2.urlopen或urllib.urlopen(已弃⽤)——在Python3.x中会使⽤quest.urlopen
在Python2.x中使⽤urllib2.Request——在Python3.x中会使⽤quest.Request
在Python2.x中使⽤urllib.quote——在Python3.x中会使⽤quest.quote
在Python2.x中使⽤urllib.urlencode——在Python3.x中会使⽤urllib.parse.urlencode
在Python2.x中使⽤cookielib.CookieJar——在Python3.x中会使⽤http.CookieJar
异常处理:在Python2.x中使⽤urllib2.URLError,urllib2.HTTPError——在Python3.x中会使⽤HTTPError 注:在Python3.3后urllib2已经不能再⽤,所有urllib2全部⽤quest来代替。
PUT⼀个请求:
quest
DATA=b'some data'
req = quest.Request(url='localhost:8080', data=DATA, method='PUT')
quest.urlopen(req) as f:
pass
print(f.status)
ason)
基本的HTTP认证:
quest
auth_handler = quest.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
uri='mahler:8092/site-updates.py',

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。