urllib库(1)

一、介绍

urllib库可以用来访问一些不需要验证的网络资源和Cookie等,主要有四个模块组成,分别是urllib.request,urllib.parse,urllib.error,urllib.robotparser。urllib.request模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程,同时它还带有处理授权验证(authenticaton)、重定向(redirection)、浏览器Cookies以及其他内容,parse库主要用来解析URL,error中包含了可能的异常类型。

二、基本使用

1、发送简单请求(urllib.request.urlopen)

import urllib.request

response = urllib.request.urlopen('http://www.baidu.com')
print (response.read().decode('utf-8'))

返回response可能是HTTPResposne类型的对象,它主要包含read()、readinto()、getheader(name)、getheaders()、fileno()等方法,以及msg、version、status、reason、debuglevel、closed等属性。

response.status             #获取状态码

200               

response.getheader('server')#获取header中对应项的值
BWS/1.1          

response.info()              #获取header中的全部信息
Accept-Ranges: bytes
Cache-Control: no-cache
Content-Length: 227
Content-Type: text/html
Date: Wed, 28 Mar 2018 00:49:16 GMT
Last-Modified: Thu, 15 Mar 2018 08:23:00 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Pragma: no-cache
Server: BWS/1.1
Set-Cookie: BD_NOT_HTTPS=1; path=/; Max-Age=300
Set-Cookie: BIDUPSID=A818A688506452DAF0B4135CD343ACE4; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1522198156; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=0
X-Ua-Compatible: IE=Edge,chrome=1
Connection: close
'''

2、GET和POST(urlopen中的data参数)

第一种说法:

GET请求的数据会附在URL之后,以' ? '分割URL和传输数据,参数之间以' & '相连,数据为字母/数字时,原样发送;空格变为' + ';中文/其他字符,则加密(不是转码吗?)。而POST则是把提交的数据放置在HTTP包的包体中,因此无法直接看到。

实际上GET的数据可以以' data '的形式在urlopen()中直接加入,

关于编码,我找到了这个据网站采用的编码不同,或是gbk或是utf-8,赋赋予不同的编码,进行不同的url转码。

GBK格式,一个中文字符转为%xx%xx,共两组;

utf-8格式,一个中文字符转为%xx%xx%xx,共三组。

POST的请求方式往往需要header信息,或者其他参数,一般来讲,只需要User-Agent一项。

第二种说法:

这里请求的站点是httpbin.org,它可以提供HTTP请求测试。本次我们请求的URL为http://httpbin.org/post, 这个链接可以用来测试POST请求,它可以输出请求的一些信息,其中包含我们传递的data参数。

我们传递的参数出现在了form字段中,这表明是模拟了表单提交的方式,以POST方式传输数据。

3、Request(headers信息的修改)

  • 参数url用于请求URL,这是必传参数,其他都是可选参数。

  • 参数data如果要传,必须传bytes(字节流)类型的。如果它是字典,可以先用urllib.parse模块里的urlencode()编码。

  • 参数headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add_header()方法添加。

添加请求头最常用的用法就是通过修改User-Agent来伪装浏览器,默认的User-Agent是Python-urllib,我们可以通过修改它来伪装浏览器。比如要伪装火狐浏览器,你可以把它设置为:

  • 参数origin_req_host指的是被请求方的host名称或者IP地址。

  • 参数unverifiable表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True`。

  • 参数method是一个字符串,用来指示请求使用的方法,比如GET、POST和PUT等,默认为GET,添加data后自动改为POST。

方法和属性

headers参数

4、handler和opener

我们可以把handler理解为各种处理器,有专门处理登录验证的,有处理Cookies的,有处理代理设置的。利用它们,我们几乎可以做到HTTP请求中所有的事情。

urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,例如default_open()、protocol_request()等。

各种子类(非全部)如下

  • HTTPDefaultErrorHandler:用于处理HTTP响应错误,错误都会抛出HTTPError类型的异常。

  • HTTPRedirectHandler:用于处理重定向。

  • HTTPCookieProcessor:用于处理Cookies。

  • ProxyHandler:用于设置代理,默认代理为空。

  • HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表。

  • HTTPBasicAuthHandler:用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。

另一个比较重要的类就是OpenerDirector,我们可以称为Opener。我们之前用过urlopen()这个方法,实际上它就是urllib为我们提供的一个Opener。之前使用的Request和urlopen()相当于类库为你封装好了极其常用的请求方法,利用它们可以完成基本的请求,但是现在不一样了,我们需要实现更高级的功能,所以需要深入一层进行配置,使用更底层的实例来完成操作,所以这里就用到了Opener。

Opener可以使用open()方法,返回的类型和urlopen()如出一辙。那么,它和Handler有什么关系呢?简而言之,就是利用Handler来构建Opener。

4.1 验证

有些网站在打开时就会弹出提示框,直接提示你输入用户名和密码,验证成功后才能查看页面,借助HTTPBasicAuthHandler就可以完成

这里首先实例化HTTPBasicAuthHandler对象,其参数是HTTPPasswordMgrWithDefaultRealm对象,它利用add_password()添加进去用户名和密码,这样就建立了一个处理验证的Handler。

接下来,利用这个Handler并使用build_opener()方法构建一个Opener,这个Opener在发送请求时就相当于已经验证成功了。

接下来,利用Opener的open()方法打开链接,就可以完成验证了。这里获取到的结果就是验证后的页面源码内容。

4.2 设置代理

有时服务器为了避免承受过多的访问,会限制爬虫的次数。这时就需要代理。

4.2 Cookie

之前用来打开URL的都是默认的opener,除了代理的时候,自己设置了一个。这样的opener一般只能输入URL,data和timeout参数。而对于一些网站为了识别用户身份,而进行session(会话)跟踪而存储在用户本地终端的数据(通常经过加密)。

  • 保存cookie数据为文件:需要FileCookieJar这个对象(MozillaCookieJar和LWPCookieJar),这两种保存的格式不一样,

  • 读取文件中的cookie

5、异常处理(urllib.error模块)

urllib的error模块定义了由request模块产生的异常。如果出现了问题,request模块便会抛出error模块中定义的异常。

5.1 URLError

URLError类来自urllib库的error模块,它继承自OSError类,是error异常模块的基类,由request模块生的异常都可以通过捕获这个类来处理。它具有一个属性reason,即返回错误的原因。

结果输出

5.2 HTTPError

它是URLError的子类,专门用来处理HTTP请求错误,比如认证请求失败等。它有如下3个属性。

  • code:返回HTTP状态码,比如404表示网页不存在,500表示服务器内部错误等。

  • reason:同父类一样,用于返回错误的原因。

  • headers:返回请求头。

输出

较好的写法是

有时候,reason属性返回的不一定是字符串,也可能是一个对象。

输出

reason属性的结果是socket.timeout类。所以,这里我们可以用isinstance()方法来判断它的类型,作出更详细的异常判断。

Last updated

Was this helpful?