51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

运维学python之爬虫基础篇(三)urllib模块高级用法

1 添加头信息 {#1-}

1.1 User-Agent {#1-1-user-agent}

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

[sourcecode language="plain"]
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)
[/sourcecode]

①通过 Request.add_header(key, val)添加字典形式的头信息,不能传多个头信息,前面的会被后面的覆盖。User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。如何获取User-Agetn信息呢?

可以用火狐或者谷歌浏览器,F12打开调试模式,我用的火狐,截图如下:
运维学python之爬虫基础篇(三)urllib模块高级用法_https://www.tiejiang.org_python_第1张

1.2 Referer {#1-2-referer}

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

[sourcecode language="plain"]

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

[/sourcecode]

2 ProxyHandler {#2-proxyhandler}

[sourcecode language="plain"]
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') ③
[/sourcecode]

①创建一个代理处理器ProxyHandler,接收的参数类型为字典{'协议': '代理ip: 端口'}

②从一个proxy_handler程序列表中创建一个opener对象,urllib.request.urlopen()函数实际上是使用的是默认的opener,这里相当于定制了自己的opener

③通过opener对象打开url

3 异常处理urllib.error {#3-urllib-error}

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

3.1 URLError {#3-1-urlerror}

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

[sourcecode language="plain"]

-*- 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)
[/sourcecode]

执行结果返回如下图:
运维学python之爬虫基础篇(三)urllib模块高级用法_https://www.tiejiang.org_python_第5张

3.2 HTTPError异常 {#3-2-httperror-}

[sourcecode language="plain"]

-*- 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)
[/sourcecode]

执行文件结果:
运维学python之爬虫基础篇(三)urllib模块高级用法_https://www.tiejiang.org_python_第6张

3.3 urllib.error.ContentTooShortError {#3-3-urllib-error-contenttooshorterror}

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

[sourcecode language="plain"]

-*- 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)
[/sourcecode]

3.4 HTTPError和URLError同时使用 {#3-4-httperror-urlerror-}

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

赞(0)
未经允许不得转载:工具盒子 » 运维学python之爬虫基础篇(三)urllib模块高级用法