urllib详细版
urllib是python内置的处理HTTP请求的库,主要包含以下四个模块
- request 模块,是最基本的处理HTTP请求的模块。
- error 异常处理模块,如果出现请求错误,可以捕获这些错误,保证程序不会意外终止。
- parse 模块是一个工具模块,提供了处理url的很多方法。拆分,解析,合并等等。
- robotparser,主要用来识别网站的robots.txt文件,判断哪些网站可以爬取。
一 、发送请求
使用urllib的request模块可以发送请求,并且响应response
- URLopen()
- urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理authenticaton(授权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。
我们来感受一下它的强大之处,以 Python 官网为例,我们来把这个网页抓下来:
- urllib.request 模块提供了最基本的构造 HTTP 请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理authenticaton(授权验证),redirections(重定向),cookies(浏览器Cookies)以及其它内容。
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))
response返回的是HTTPResposne 类型的对象,包含的方法有read()、readinto()、getheader(name)、getheaders()、fileno() 等方法和 msg、version、status、reason、debuglevel、closed 等属性。
例如调用 read() 方法可以得到返回的网页内容,调用 status 属性就可以得到返回结果的状态码,如 200 代表请求成功,404 代表网页未找到等。
import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
运行结果如下:
200
[('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('X-Clacks-Overhead', 'GNU Terry Pratchett'), ('Content-Length', '47397'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 01 Aug 2016 09:57:31 GMT'), ('Via', '1.1 varnish'), ('Age', '2473'), ('Connection', 'close'), ('X-Served-By', 'cache-lcy1125-LCY'), ('X-Cache', 'HIT'), ('X-Cache-Hits', '23'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
nginx
可见,三个输出分别输出了响应的状态码,响应的头信息,以及通过调用 getheader() 方法并传递一个参数 Server 获取了 headers 中的 Server 值,结果是 nginx,意思就是服务器是 nginx 搭建的。
利用以上最基本的 urlopen() 方法,我们可以完成最基本的简单网页的 GET 请求抓取。
如果我们想给链接传递一些参数该怎么实现呢?我们首先看一下 urlopen() 函数的API:
def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None, cadefault=False, context=None):
可以发现除了第一个参数可以传递 URL 之外,我们还可以传递其它的内容,比如 data(附加数据)、timeout(超时时间)等等。
data参数:
data的参数是可选的,如果要添加data参数,必须是bytes类型。通过bytes()方法可以转化,data有参数请求方式会从之前的get请求换为post 请求
import urllib.parse
import urllib.request data = bytes(urllib.parse.urlencode({'word': 'hello'}), encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())
在这里我们传递了一个参数 word,值是 hello。它需要被转码成bytes(字节流)类型。其中转字节流采用了 bytes() 方法,第一个参数需要是 str(字符串)类型,需要用 urllib.parse 模块里的 urlencode() 方法来将参数字典转化为字符串。第二个参数指定编码格式,在这里指定为 utf8。
timeout参数:
timeout参数设置超时时间,单位是秒。如果请求超过这个时间还没有得到响应,就会抛出异常。如果没有设定的话,就会使用全局的默认时间。支持HTTP,HTTPS,FTP!
我们可以设置超时时间来控制网页爬取时间超过规定时间就跳出,使用try except语句是实现。
import socket
import urllib.request
import urllib.error try:
response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
还有 context 参数,它必须是 ssl.SSLContext 类型,用来指定 SSL 设置。
cafile 和 capath 两个参数是指定 CA 证书和它的路径,这个在请求 HTTPS 链接时会有用。
cadefault 参数现在已经弃用了,默认为 False。
详细文档:https://docs.python.org/3/library/urllib.request.html
Request
urlopen()可以实现简单的请求,但是不能构建一个完整的请求。所以可以用Request类来构建一个完整的请求。
import urllib.request
request = urllib.request.Request('https://python.org')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
观察还是用urlopen()来发起的请求,只不过参数不再是url,而是一个request对象。
Request的参数:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
参数解释:
url:请求的url ,必传参数。
data: 类型是bytes类型,如果是字典,使用urllib.parse中的urlencode()编码!
headers:参数是一个字典,表示请求的请求标识和载体!可以直接构造,也可以通过调用Request实例的add_header()方法来添加。
origin_host:表示请求的host名称或者IP地址!
unverifiable:参数表示这个请求是否是无法验证的,默认是False.意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True。
method:表示请求的方式GET,POST,PUT等等!!!
from urllib import request, parse url = 'http://httpbin.org/post'
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
'Host': 'httpbin.org'
}
dict = {
'name': 'Germey'
}
data = bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
headers 也可以用 add_header() 方法来添加。
req = request.Request(url=url, data=data, method='POST')
req.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')
二、处理异常
在发送Request请求的时候,可能会因为一些情况,导致异常出现,怎么办呢?如果不处理这些异常得话,程序很可能会因为报错而停止运行!所以处理异常非常有必要!
urllib 的error模块定义了由request模块产生的异常。如果出现了问题,request模块就会抛出error模块中定义的异常!
主要有URLError和HTTPError
举例:
from urllib import request,error
try:
response = request.urlopen("http://chuanshengkj.com/index.htm")
except error.URLError as e :
print(e.reason)
我们打开一个不存在的页面,照理来说应该会报错,但是这时我们捕获了 URLError 这个异常,运行结果如下:
Not Found
from urllib import request,error
try:
response = request.urlopen("http://cuiqingcai.com/index.htm")
except error.HTTPError as e :
print(e.reason,e.code,e.headers,sep='\n')
运行结果:
Not Found
404
Server: nginx/1.10.3 (Ubuntu)
Date: Thu, 12 Sep 2019 07:20:12 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Set-Cookie: PHPSESSID=vsnopftnnk0gfjrk3qfljvq6v5; path=/
Pragma: no-cache
Vary: Cookie
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Link: <https://cuiqingcai.com/wp-json/>; rel="https://api.w.org/"
HTTPError,它有三个属性。
- code,返回 HTTP Status Code,即状态码,比如 404 网页不存在,500 服务器内部错误等等。
- reason,同父类一样,返回错误的原因。
- headers,返回 Request Headers。
因为 URLError 是 HTTPError 的父类,所以我们可以先选择捕获子类的错误,再去捕获父类的错误,所以上述代码更好的写法如下:
from urllib import request, error try:
response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
print(e.reason)
else:
print('Request Successfully')
这样我们就可以做到先捕获 HTTPError,获取它的错误状态码、原因、Headers 等详细信息。如果非 HTTPError,再捕获 URLError 异常,输出错误原因。最后用 else 来处理正常的逻辑,这是一个较好的异常处理写法
urllib详细版的更多相关文章
- iOS App上架流程(2016详细版)
iOS App上架流程(2016详细版) 原文地址:http://www.jianshu.com/p/b1b77d804254 感谢大神整理的这么详细 一.前言: 作为一名iOSer,把开发出来的Ap ...
- 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)
手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版) SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式, ...
- 使用keil建立标准STM32工程模版(图文详细版!)
1. 模板工程的创建(超级详细版,使用的是keil 4.5版本) 1.1创建工程目录 良好的工程结构能让文件的管理更科学,让开发更容易更方便,希望大家养成良好的习惯,使用具有合理结构的工程目录,当 ...
- doc命令大全(详细版)
doc命令大全(详细版) 1 echo 和 @回显命令@ #关闭单行回显echo off #从下一行开始关闭回显@echo ...
- SpringBoot整合Mybatis完整详细版二:注册、登录、拦截器配置
接着上个章节来,上章节搭建好框架,并且测试也在页面取到数据.接下来实现web端,实现前后端交互,在前台进行注册登录以及后端拦截器配置.实现简单的未登录拦截跳转到登录页面 上一节传送门:SpringBo ...
- SpringBoot整合Mybatis完整详细版
记得刚接触SpringBoot时,大吃一惊,世界上居然还有这么省事的框架,立马感叹:SpringBoot是世界上最好的框架.哈哈! 当初跟着教程练习搭建了一个框架,传送门:spring boot + ...
- phpStudy模式下安装ssl证书,详细版
phpStudy模式下安装ssl证书,详细版 2017年12月16日 14:27:38 骑着蚂蚁追大象 阅读数:4232 标签: phpstudy安装ssl证书 更多 个人分类: php 版权声明 ...
- caffe学习--使用caffe中的imagenet对自己的图片进行分类训练(超级详细版) -----linux
http://blog.csdn.net/u011244794/article/details/51565786 标签: caffeimagenet 2016-06-02 12:57 9385人阅读 ...
- MySQL与MariaDB核心特性比较详细版v1.0(覆盖mysql 8.0/mariadb 10.3,包括优化、功能及维护)
注:本文严禁任何形式的转载,原文使用word编写,为了大家阅读方便,提供pdf版下载. MySQL与MariaDB主要特性比较详细版v1.0(不含HA).pdf 链接:https://pan.baid ...
随机推荐
- vue v-for直接循环数字
<svg class="icon" aria-hidden="true" v-for="index of 5" :key=" ...
- Redis 5.0
1.概述默认端口号:6379 redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(s ...
- 模仿抽奖转盘,并且用cookie记录历史次数
自己制作了一个模仿抽奖转盘的小游戏,代码比较简单,规则是只有三次抽奖机会,并且浏览器会记录抽奖的次数, 代码如下 <!DOCTYPE html> <html> <head ...
- Python学习之数据库
9.6 表的查询 [结构]select distinct 字段1,字段2 from 表名 where 条件 group by 字段 having 筛选 order by 字段 limit 限制条数 [ ...
- #Java学习之路——基础阶段二(第十三篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- USACO4.3 Letter Game【枚举·细节】
题意 这道题的题目描述让我好一阵蒙,简述一下题意吧: 给定一些字母的价值(如图所示),给出一个字符串(长度在$3$到$7$之间,可以出现重复的字母)和一个单词库.定义一个单词的价值就是它的字母的价值之 ...
- GitHub高级搜索
GitHub是开发目前最为活跃的开源网站和代码托管地,虽然我们经常使用GitHub,关注各种开源项目,但可能有很多人并不太了解GitHub的搜索功能的使用.GitHub提供了简单搜索和高级搜索,高级 ...
- Revo Uninstaller Pro - 真正彻底卸载软件不留垃圾的强大神器!(清理安装残留文件/注册表)
大家都知道 Windows 在卸载软件时总是不够彻底,系统C盘总会留下大量难以辨别和清理的垃圾文件和临时文件,时间长了注册表也会变得非常臃肿,不仅浪费硬盘空间,而且也会明显拖慢系统响应和启动速度. R ...
- MyBatis批量插入性能及问题
1.mybatis三种批量插入方式对比 2.Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案 3.Mybatis批量插入引发的血案 4.Oracle批量插入数据SQL语句太长出错
- [转帖]Windows与Linux的命令行命令对比
Windows与Linux的命令行命令对比 https://www.cnblogs.com/sztom/p/10785140.html * Windows不区分大小写,Linux区分大小写的. sn ...