爬虫基础(3)发送请求之urllib库与urllib3库的使用

本文介绍了Python中的urllib库和urllib3库,详细阐述了urllib库的request、parse、error和robotparser模块,包括发送请求、解析链接、处理异常和分析Robots协议。同时,讲解了urllib3库的特性,如线程安全、连接池、HTTP客户端功能等,并给出了使用示例。最后,通过爬取百度图片的实例展示了如何使用urllib库和urllib3库进行网络请求。
摘要由CSDN通过智能技术生成

一. urllib库与urllib3库的简介

python3中有urllib和urllib3两个库,其中urllib几乎是python2.7中urllib和urllib2两个模块的集合,所以我们最常用的是模块urllib模块,而urllib3则作为一个拓展模块使用。

(一)什么是Urllib库

Urllib库是Python中的一个功能强大、用于操作URL,并在做爬虫的时候经常要用到的库。在Python2.x中,分为Urllib库和Urllib2库,Python3.x之后都合并到Urllib库中,使用方法稍有不同。下面介绍的是Python3中的urllib库。

urllib 中包含四个模块,分别是 requestparseerrorrobotparser,他们各自的主要作用是:

  • request:发送请求
  • parse:解析链接
  • error:处理异常
  • robotparser:分析 Robots 协议

以下我们将会分别讲解 Urllib 中各模块的使用方法,但是由于篇幅问题,本文只会涉及模块中比较常用的内容。

在开始讲解前,先给大家提供一个用于测试的网站:发送请求,这个网站可以在页面上返回所发送 请求 的相关信息,十分适合练习使用。

(二)什么是urllib3库

Urllib3是一个功能强大,条理清晰,用于HTTP客户端的Python库,许多Python的原生系统已经开始使用urllib3。Urllib3提供了很多python标准库里所没有的重要特性:

  • 线程安全
  • 连接池
  • 客户端SSL/TLS验证
  • 文件分部编码上传
  • 协助处理重复请求和HTTP重定位
  • 支持压缩编码
  • 支持HTTP和SOCKS代理
  • 100%测试覆盖率

(三)urllib库与urllib3库的关系

我们要明白的是,urllib库和urllib3库没什么关系,这两个库是两个完全不同的包。urllib库并不是在python3.X版本中的urllib3库。

二. urllib库模块详析

本节我们分别详细的讲述一下urllib库的四个重要的模块。关于urllib库的详细内容可参考其官方文档:https://docs.python.org/3/library/urllib.html。下面我们着重说一下前三个urllib模块(最后一个模块应用的频率较少,此处我们只作了解)。

(一)发送请求

request 模块是最基本的 HTTP 请求模块,可以用来模拟发送请求,就像在浏览器里输入网址,然后回车一样,只需要给库方法传入 URL 及额外的参数,就可以模拟实现这个过程了。同时它还带有处理授权验证( authenticaton )、重定向( redirection 、浏览器 Cookies 及其他内容。使用 urllib 的 request 模块,我们可以很方便地实现请求的发送并得到响应。

1. urlopen方法

urlopen方法的作用是快速发送一个简单的网络请求,该方法的调用格式如下:

urllib.request.urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, cafile=None, capath=None, cadefault=False, context=None)

urlopen 方法无疑是 request 模块中最常用的方法之一,常见的参数说明如下:

  • url:必填,字符串,指定目标网站的 URL。
  • data:指定表单数据,该参数默认为 None,此时 urllib 使用 GET 方法 发送请求;当给参数赋值后,urllib 使用 POST 方法 发送请求,并在该参数中携带表单信息(bytes 类型)。例如下面这个例子:
from urllib import request, parse

data = bytes(parse.urlencode({
   'word': 'hello'}), encoding='utf-8')
response = request.urlopen('http://httpbin.org/post', data=data)
print(response.read().decode('utf-8'))

# 运行结果:
{
   
  "args": {
   }, 
  "data": "", 
  "files": {
   }, 
  "form": {
   
    "word": "hello"
  }, 
  "headers": {
   
    "Accept-Encoding": "identity", 
    "Content-Length": "10", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.6", 
    "X-Amzn-Trace-Id": "Root=1-5f6a064d-10cc915066a3cda010364b70"
  }, 
  "json": null, 
  "origin": "111.44.171.116", 
  "url": "http://httpbin.org/post"
}

代码解析:我们传递了一个参数word,其值是“hello”。他需要被转码成bytes(字节流)类型。其中转字节流采用bytes()方法,该方法的第一个参数需要是str(字符串)类型,需要用parse模块中的urlencode()方法将参数字典转换为字符串;第二个参数指定编码格式,这里指定为“utf-8”。本次请求的站点是httpbin.org,他可以提供HTTP请求测试。当请求被发送后,我们将返回结果以read()方法打印出来。

  • timeout:可选参数,用来指定等待时间,若超过指定时间还没获得响应,则抛出一个异常。如果不指定该参数,就会使用全局默认时间。它支持HTTP、HTTPS、FTP请求。
from urllib import request

response = request.urlopen('http://httpbin.org/get', timeout=0.1)
print(response.read())

# 运行结果:
Traceback (most recent call last):
  ......
urllib.error.URLError: <urlopen error timed out>

此处我们设置超时时间是0.1秒。程序0.1秒过后,服务器依然没有响应,于是抛出了URLError异常。该异常属于urllib.error模块,错误原因是超时。因此,我们可以通过设置这个超时时间来控制一个网页如果长时间未响应,就跳过它的抓取。一般利用try … except语句来实现。

该方法始终返回一个 HTTPResponse 对象,HTTPResponse 对象常见的属性和方法如下:

  • geturl():返回 URL
  • getcode():返回状态码
  • getheaders():返回全部响应头信息
  • getheader(header):返回指定响应头信息
  • info():返回响应头信息
  • read():返回响应体(bytes 类型),通常需要使用 decode('utf-8') 将其转化为 str 类型
from urllib import request

url = 'http://www.httpbin.org/get'
response = request.urlopen(url)
print(type(response))
print(response.geturl())
print(response.getcode())
print(response.getheaders())
print(response.getheader('Connection'))
print(response.info())
print(response.read().decode('utf-8'))

# 运行结果
>>> <class 'http.client.HTTPResponse'>
>>> http://www.httpbin.org/get
>>> 200
>>> [('Date', 'Tue, 08 Sep 2020 06:24:09 GMT'), ('Content-Type', 'application/json'), ('Content-Length', '283'), ('Connection', 'close'), ('Server', 'gunicorn/19.9.0'), ('Access-Control-Allow-Origin', '*'), ('Access-Control-Allow-Credentials', 'true')]
>>> close
>>> Date: Tue, 08 Sep 2020 10:11:28 GMT
Content-Type: application/json
Content-Length: 283
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
>>> {
   
  "args": {
   }, 
  "headers": {
   
    "Accept-Encoding": "identity", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Python-urllib/3.6", 
    "X-Amzn-Trace-Id": "Root=1-5f572389-909a186816689b48fdf37700"
  },
  "origin": "221.207.18.109", 
  "url": "http://www.httpbin.org/get"
}

下面是使用urlopen()方法快速抓取百度首页面的代码:

from urllib import request

url = 'http://www.baidu.com'
response = request.urlopen(url)
data = response.read()
with open("1.html", 'wb') as f:
    f.write(data)

代码的逻辑很简单,首先定义一个目标网页URL,然后通过urlopen()方法访问目标网页,该方法模拟浏览器发送请求,返回一个 HTTPResponse 对象;再以read()方法读取响应内容;最后将内容保存到本地文件中。

2. Request对象

实际上,我们还可以给 urllib.request.open() 方法传入一个 Request 对象作为参数。为什么还需要使用 Request 对象呢?因为在上面的参数中我们无法指定 请求头部(headers),而headers在爬取一些设置的反爬的网页数据信息时,可以模拟浏览器访问这些网页,所以他在网络爬虫过程中起着重要的作用。

很多网站可能会首先检查请求头部中的 USER-AGENT 字段来判断该请求是否由网络爬虫程序发起。但是通过修改请求头部中的 USER_AGENT 字段,我们可以将爬虫程序伪装成浏览器,轻松绕过这一层检查。这里提供一个查找常用的 USER-AGENT 的网站:https://techblog.willshouse.com/2012/01/03/most-common-user-agents/

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

参数说明如下:

  • url:指定目标网站的 URL
  • data:发送 POST 请求时提交的表单数据,默认为 None
  • headers:发送请求时附加的请求头部,默认为 {}
  • origin_req_host:请求方的 host 名称或者 IP 地址,默认为 None
  • unverifiable:请求方的请求无法验证,默认为 False
  • method:指定请求方法,默认为 None
from urllib import request

url = 'http://www.httpbin.org/headers'
headers = {
   
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
req = request.Request(url, headers=headers, method='GET')
res = request.urlopen(req)
html = res.read().decode('utf-8')
print(html)

# 运行结果:
{
   
  "headers": {
   
    "Accept-Encoding": "identity", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36", 
    "X-Amzn-Trace-Id": "Root=1-5f575683-21240e2a6e35000b2793245b"
  }
}

当我们以POST请求方式发送请求时:


                
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值