1 添加头信息

1.1 User-Agent

有些网站,如果你按照urllib.request.urlopen('https://www.baidu.com') 这种方式打开,服务器有可能不会响应,所以要完全模仿浏览器访问,我们需要加入User-Agent信息,示例代码如下:

from urllib import request

req = request.Request('https://www.baidu.com')
req.add_headers('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0') ①

response = request.urlopen(req)

①通过 Request.add_header(key, val)添加字典形式的头信息,不能传多个头信息,前面的会被后面的覆盖。
User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。如何获取User-Agetn信息呢?
可以用火狐或者谷歌浏览器,F12打开调试模式,我用的火狐,截图如下:
运维学python之爬虫基础篇(三)urllib模块高级用法

1.2 Referer

Referer 首部包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 首部识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。有些服务器会识别headers中的referer是不是它自己,如果不是,不会响应,所以我们还可以在headers中加入referer。
可以打开F12看下Referer具体效果,我手动输入网址打开百度后,头信息如下:
运维学python之爬虫基础篇(三)urllib模块高级用法
我在直接点击网页上的新闻连接,看下头信息内容:
运维学python之爬虫基础篇(三)urllib模块高级用法
是不是多了Referer,显示来源页面是我手动打开的百度首页。
添加Referer方式与添加User-Agent一样,如下:

略
req.add_headers('Referer', 'https://www.baidu.com') 
略

2 ProxyHandler

proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'}) ①
opener = urllib.request.build_opener(proxy_handler) ②
# This time, rather than install the OpenerDirector, we use it directly:
 opener.open('http://www.example.com/login.html')  ③

①创建一个代理处理器ProxyHandler,接收的参数类型为字典{'协议': '代理ip: 端口'}
②从一个proxy_handler程序列表中创建一个opener对象,urllib.request.urlopen()函数实际上是使用的是默认的opener,这里相当于定制了自己的opener
③通过opener对象打开url

3 异常处理urllib.error

urllib.error模块定义了由urllib.request引起的异常的异常类。基本的异常类是URLError。
运维学python之爬虫基础篇(三)urllib模块高级用法

3.1 URLError

URLError是OSError的一个子类,HTTPError是URLError的一个子类我们先来看URLError异常

# -*- coding: utf-8 -*-

from urllib import request
from urllib import error

if __name__ == "__main__":
    req = request.Request('http://www.demo.com')
    try:
        response = request.urlopen(req)
        html = response.read().decode('utf-8')
        print(html)
    except error.URLError as e:
        print(e.reason)

执行结果返回如下图:
运维学python之爬虫基础篇(三)urllib模块高级用法

3.2 HTTPError异常

# -*- coding: utf-8 -*-

from urllib import request
from urllib import error

if __name__ == '__main__':
    req = request.Request('http://mirrors.163.com/centos/7.4.1708/isos/x86_64/sha2sum.txt')
    try:
        response = request.urlopen(req)
    except error.HTTPError as e:
        print(e)

执行文件结果:
运维学python之爬虫基础篇(三)urllib模块高级用法

3.3 urllib.error.ContentTooShortError

urllib.error.ContentTooShortError异常是因为文件下载不完全导致的错误,这个错误不好复现,就简单举例说明:

# -*- coding: utf-8 -*-

from urllib import request
from urllib import error

if __name__ == "__main__":
    req = request.Request('https://download.demo.com')
    filename = 'E:\test3.txt'
    try:
        request.urlretrieve(req, filename)
    except error.ContentTooShortError as e:
        print(e)

3.4 HTTPError和URLError同时使用

同时使用,需要将HTTPError放在URLError的前面,因为HTTPError是URLError的一个子类。如果URLError放在前面,出现HTTP异常会先响应URLError,这样HTTPError就捕获不到错误信息了。
运维学python之爬虫基础篇(三)urllib模块高级用法
如果不用上面的方法,也可以使用hasattr函数判断URLError的属性,如果含有reason属性表明是URLError,如果含有code属性表明是HTTPError。
运维学python之爬虫基础篇(三)urllib模块高级用法