Python3中urllib详细使用方法(header,代理,超时,认证,异常处理)

                      Python 3 中的 urllib 库的用法。urllib 是 Python 标准库中用于网络请求的库。该库有四个模块,分别是urllib.requesturllib.errorurllib.parseurllib.robotparser。其中urllib.requesturllib.error两个库在爬虫程序中应用比较频繁。

urllib是python的一个获取url(Uniform Resource Locators,统一资源定址器)了,我们可以利用它来抓取远程的数据进行保存哦,下面整理了一些关于urllib使用中的一些关于header,代理,超时,认证,异常处理处理方法,下面一起来看看。

python3 抓取网页资源的 N 种方法

1.1、最简单直接用urllib.request模块的urlopen()获取页面,page的数据格式为bytes类型,需要decode()解码,转换成str类型。

urlopen返回对象提供方法:

-         read() , readline() ,readlines() , fileno() , close() :对HTTPResponse类型数据进行操作

-         info():返回HTTPMessage对象,表示远程服务器返回的头信息

-         getcode():返回Http状态码。如果是http请求,200请求成功完成;404网址未找到

-         geturl():返回请求的url

1import urllib.request
2 
3 response = urllib.request.urlopen('http://python.org/')
4 
5 html = response.read()#获取网页源代码
6print(html.decode('utf-8'))    # 转化为 utf-8 编码

1.2 设置请求超时

有些请求可能因为网络原因无法得到响应。因此,我们可以手动设置超时时间。当请求超时,我们可以采取进一步措施,例如选择直接丢弃该请求或者再请求一次。

import urllib.request

url = "http://tieba.baidu.com"
response = urllib.request.urlopen(url, timeout=1)
print(response.read().decode('utf-8'))

又例:

#! /usr/bin/env python3

import socket

import urllib.request

# timeout in seconds

timeout = 2

socket.setdefaulttimeout(timeout)

# this call to urllib.request.urlopen now uses the default timeout

# we have set in the socket module

req = urllib.request.Request('http://www.python.org/')

a = urllib.request.urlopen(req).read()

print(a)

2、使用 Request

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

 

  • url 参数是请求链接,这个是必传参数,其他的都是可选参数。
  • 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等

2.1简单的使用Request

使用request()来包装请求,再通过urlopen()获取页面。

使用 Request 伪装成浏览器发起 HTTP 请求。如果不设置 headers 中的 User-Agent,默认的User-AgentPython-urllib/3.5。可能一些网站会将该请求拦截,所以需要伪装成浏览器发起请求。我使用的 User-Agent 是 Chrome 浏览器。

import urllib.request

url = "http://tieba.baidu.com/"
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 = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

2.2、发送数据

#! /usr/bin/env python3

import urllib.parse

import urllib.request

url = 'http://localhost/login.php'

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'

values = {  'act' : 'login',  'login[email]' : '[email protected]',  'login[password]' : '123456'  }

data = urllib.parse.urlencode(values)

req = urllib.request.Request(url, data)

req.add_header('Referer', 'http://www.python.org/')

response = urllib.request.urlopen(req)

the_page = response.read()

print(the_page.decode("utf8"))

又例如:

from urllib import request, parse
 2 url = r'http://www.lagou.com/jobs/positionAjax.json?'
 3 headers = {
 4     'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
 5                   r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
 6     'Referer': r'http://www.lagou.com/zhaopin/Python/?labelWords=label',
 7     'Connection': 'keep-alive'
 8 }
 9 data = {
10     'first': 'true',
11     'pn': 1,
12     'kd': 'Python'
13 }
14 data = parse.urlencode(data).encode('utf-8')
15 req = request.Request(url, headers=headers, data=data)
16 page = request.urlopen(req).read()
17 page = page.decode('utf-8')

 data需要被转码成字节流。而 data 是一个字典。我们需要使用 urllib.parse.urlencode() 将字典转化为字符串。再使用 bytes() 转为字节流。最后使用 urlopen() 发起请求,请求是模拟用 POST 方式提交表单数据。 

2.3、发送数据和header

#! /usr/bin/env python3

import urllib.parse

import urllib.request

url = 'http://localhost/login.php'

user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'

values = {  'act' : 'login',  'login[email]' : '[email protected]',  'login[password]' : '123456'  }

headers = { 'User-Agent' : user_agent }

data = urllib.parse.urlencode(values)

req = urllib.request.Request(url, data, headers)

response = urllib.request.urlopen(req)

the_page = response.read()

print(the_page.decode("utf8"))

3、Request 高级用法

如果我们需要在请求中添加代理、处理请求的 Cookies,我们需要用到HandlerOpenerDirector

1) Handler
Handler 的中文意思是处理者、处理器。 Handler 能处理请求(HTTP、HTTPS、FTP等)中的各种事情。它的具体实现是这个类 urllib.request.BaseHandler。它是所有的 Handler 的基类,其提供了最基本的Handler的方法,例如default_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(opener)方法。值得注意的是,install_opener 实例化会得到一个全局的 OpenerDirector 对象。

3.1、使用代理:

       我们已经了解了 opener 和 handler,接下来我们就通过示例来深入学习。第一个例子是为 HTTP 请求设置代理
有些网站做了浏览频率限制。如果我们请求该网站频率过高。该网站会被封 IP,禁止我们的访问。所以我们需要使用代理来突破这“枷锁”。

import urllib.request

url = "http://tieba.baidu.com/"
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'
}

proxy_handler = urllib.request.ProxyHandler({
    'http': 'web-proxy.oa.com:8080',
    'https': 'web-proxy.oa.com:8080'
})
opener = urllib.request.build_opener(proxy_handler)
urllib.request.install_opener(opener)

request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

 又例如:

#! /usr/bin/env python3

import urllib.request

proxy_support = urllib.request.ProxyHandler({'sock5': 'localhost:1080'})

opener = urllib.request.build_opener(proxy_support)

urllib.request.install_opener(opener)

 a = urllib.request.urlopen("http://www.python.org/").read().decode("utf8")

print(a)

 

3.2、认证登录

有些网站需要携带账号和密码进行登录之后才能继续浏览网页。碰到这样的网站,我们需要用到认证登录。我们首先需要使用 HTTPPasswordMgrWithDefaultRealm() 实例化一个账号密码管理对象;然后使用 add_password() 函数添加账号和密码;接着使用 HTTPBasicAuthHandler() 得到 hander;再使用 build_opener() 获取 opener 对象;最后使用 opener 的 open() 函数发起请求。

第二个例子是携带账号和密码请求登录百度贴吧,代码如下:

import urllib.request

url = "http://tieba.baidu.com/"
user = 'user'
password = 'password'
pwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
pwdmgr.add_password(None,url ,user ,password)

auth_handler = urllib.request.HTTPBasicAuthHandler(pwdmgr)
opener = urllib.request.build_opener(auth_handler)
response = opener.open(url)
print(response.read().decode('utf-8'))

HTTP 认证

#! /usr/bin/env python3

import urllib.request

# create a password manager

password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()

# Add the username and password.

# If we knew the realm, we could use it instead of None.

top_level_url = "https://www.python.org/"

password_mgr.add_password(None, top_level_url, 'rekfan', 'xxxxxx')

handler = urllib.request.HTTPBasicAuthHandler(password_mgr)

# create "opener" (OpenerDirector instance)

opener = urllib.request.build_opener(handler)

# use the opener to fetch a URL

a_url = "https://www.python.org/"

x = opener.open(a_url)

print(x.read())

# Install the opener.

# Now all calls to urllib.request.urlopen use our opener.

urllib.request.install_opener(opener)

a = urllib.request.urlopen(a_url).read().decode('utf8')

print(a)

 

3.3、Cookies设置

如果请求的页面每次需要身份验证,我们可以使用 Cookies 来自动登录,免去重复登录验证的操作。获取 Cookies 需要使用 http.cookiejar.CookieJar() 实例化一个 Cookies 对象。再用 urllib.request.HTTPCookieProcessor 构建出 handler 对象。最后使用 opener 的 open() 函数即可。

第三个例子是获取请求百度贴吧的 Cookies 并保存到文件中,代码如下

import http.cookiejar
import urllib.request

url = "http://tieba.baidu.com/"
fileName = 'cookie.txt'

cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open(url)

f = open(fileName,'a')
for item in cookie:
    f.write(item.name+" = "+item.value+'\n')
f.close()

4、HTTPResponse

从上面的例子可知, 使用 urllib.request.urlopen() 或者 opener.open(url) 返回结果是一个 http.client.HTTPResponse 对象。它具有 msg、version、status、reason、debuglevel、closed等属性以及read()、readinto()、getheader(name)、getheaders()、fileno()等函数。

5、错误解析:

发起请求难免会出现各种异常,我们需要对异常进行处理,这样会使得程序比较人性化。
异常处理主要用到两个类,urllib.error.URLErrorurllib.error.HTTPError

  • URLError
    URLError 是 urllib.error 异常类的基类, 可以捕获由urllib.request 产生的异常。
    它具有一个属性reason,即返回错误的原因。
  • 捕获 URL 异常的示例代码:
import urllib.request
import urllib.error

url = "http://www.google.com"
try:
    response = request.urlopen(url)
except error.URLError as e:
    print(e.reason)

作者:猴哥Yuri
链接:https://www.jianshu.com/p/2e190438bd9c
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

  • HTTPError HTTPError 是 UEKRrror 的子类,专门处理 HTTP 和 HTTPS 请求的错误。它具有三个属性。 1)code:HTTP 请求返回的状态码。 1)renson:与父类用法一样,表示返回错误的原因。 1)headers`:HTTP 请求返回的响应头信息。

获取 HTTP 异常的示例代码, 输出了错误状态码、错误原因、服务器响应头

import urllib.request
import urllib.error

url = "http://www.google.com"
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')

http 错误

#! /usr/bin/env python3

import urllib.request

req = urllib.request.Request('http://python.org/')

try:  

  urllib.request.urlopen(req)

except urllib.error.HTTPError as e:

  print(e.code)

print(e.read().decode("utf8"))

6、异常处理1

#! /usr/bin/env python3

from urllib.request import Request, urlopen

from urllib.error import URLError, HTTPError

req = Request('http://www.python.org/')

try:

  response = urlopen(req)

except HTTPError as e:

  print('The (www.python.org)server couldn't fulfill the request.')

  print('Error code: ', e.code)

except URLError as e:

  print('We failed to reach a server.')

  print('Reason: ', e.reason)

else:

  print("good!")

  print(response.read().decode("utf8"))

异常处理2

#! /usr/bin/env python3

from urllib.request import Request, urlopen

from urllib.error import  URLError

req = Request("http://www.python.org/")

try:

  response = urlopen(req)

except URLError as e:

  if hasattr(e, 'reason'):

    print('We failed to reach a server.')

    print('Reason: ', e.reason)

  elif hasattr(e, 'code'):

    print('The server couldn't fulfill the request.')

    print('Error code: ', e.code)

else:  print("good!")

  print(response.read().decode("utf8"))

 

 

 

你可能感兴趣的:(Python)