用Python 3开发网络爬虫

By Terrill Yang (Github: https://github.com/yttty)

你需要这些:Python3.x爬虫学习资料整理 - 知乎专栏整理而来。

本篇来自requests的基本使用

用Python 3开发网络爬虫 - Chapter 04

使用requests库

urllib 库中,有 urllib.request.urlopen(url) 的方法,实际上它是以 GET 方式请求了一个网页。 那么在 requests 中,相应的方法就是 requests.get(url) ,是不是感觉表达更明确一些?

下面我们用一个实例来感受一下:

导入并请求 https://www.baidu.com/


In [1]:
import requests

r = requests.get('https://www.baidu.com/')

请求响应的类型是 requests.models.Response


In [2]:
print(type(r))


<class 'requests.models.Response'>

状态码是200


In [3]:
print(r.status_code)


200

响应体的类型是字符串str


In [4]:
print(type(r.text))


<class 'str'>

可以得到响应的 HTTP HEADER


In [5]:
print(r.headers)


{'Transfer-Encoding': 'chunked', 'Pragma': 'no-cache', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/, __bsi=14243632104444637276_00_123_N_N_4_0303_C02F_N_N_N_0; expires=Sat, 18-Feb-17 15:45:15 GMT; domain=www.baidu.com; path=/', 'Content-Type': 'text/html', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Server': 'bfe/1.0.8.18', 'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Date': 'Sat, 18 Feb 2017 15:45:10 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:24:09 GMT'}

响应体内容


In [6]:
print(r.text)


<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>

Cookies的类型是RequestsCookieJar


In [7]:
print(r.cookies)


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>, <Cookie __bsi=14243632104444637276_00_123_N_N_4_0303_C02F_N_N_N_0 for .www.baidu.com/>]>

我们可以发现,使用了 requests.get(url) 方法就成功实现了一个 GET 请求。这倒不算什么,更方便的在于其他的请求类型依然可以用一句话来完成。

下面介绍一个很棒的demo网站,httpbin(1): HTTP Request & Response Service (http://httpbin.org) ,这个网站的介绍大概是这个样子的

Testing an HTTP Library can become difficult sometimes. RequestBin is fantastic for testing POST requests, but doesn't let you control the response. This exists to cover all kinds of HTTP scenarios. Additional endpoints are being considered.

All endpoint responses are JSON-encoded.

简单的说就是你可以对这个网站发出各类HTTP请求,来测试你的请求报文。

下面用一个实例来感受一下 requests 库的强大威力:


In [8]:
r = requests.post('http://httpbin.org/post')
print('----POST----\n', r.text)
r = requests.put('http://httpbin.org/put')
print('----PUT----\n', r.text)
r = requests.delete('http://httpbin.org/delete')
print('----DELETE----\n', r.text)
r = requests.head('http://httpbin.org/get')
print('----HEAD----\n', r.text)
r = requests.options('http://httpbin.org/get')
print('----OPTIONS----\n', r.text)


----POST----
 {
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "0", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/post"
}

----PUT----
 {
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "0", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/put"
}

----DELETE----
 {
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "0", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/delete"
}

----HEAD----
 
----OPTIONS----
 

其实这只是 requests 库的冰山一角,更多的还在后面呢。

GET请求

HTTP 中最常见的请求之一就是 GET 请求,我们首先来详细了解下利用 requests 来构建 GET 请求的方法以及相关属性方法操作。

首先让我们来构建一个最简单的GET请求,请求 httpbin.org/get ,它会判断如果你是 GET 请求的话,会返回响应的请求信息。


In [9]:
r = requests.get('http://httpbin.org/get')
print(r.text)


{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/get"
}

可以发现我们成功发起了get请求,请求的链接和头信息都有相应的返回。

那么 GET 请求,如果要附加额外的信息一般是怎样来添加?没错,那就是直接当做参数添加到url后面。

比如现在我想添加两个参数,名字namegermey,年龄age22。构造这个请求链接是不是我们要直接写成

r = requests.get("http://httpbin.org/get?name=germey&age=22")

可以是可以,但是不觉得很不人性化吗?一般的这种信息数据我们会用字典来存储,那么怎样来构造这个链接呢?

{"name": "germey", "age": 22}

同样很简单,利用params这个参数就好了。

实例如下:


In [10]:
data = {
    'name': 'germey',
    'age': 22
}

r = requests.get("http://httpbin.org/get", params=data)
print(r.text)


{
  "args": {
    "age": "22", 
    "name": "germey"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/get?name=germey&age=22"
}

通过返回信息我们可以判断,请求的链接自动被构造成了 http://httpbin.org/get?age=22&name=germey ,是不是很方便?

另外,网页的返回类型实际上是str类型,但是它很特殊,是Json的格式,所以如果我们想直接把返回结果解析,得到一个字典dict格式的话,可以直接调用json()方法。

用一个实例来感受一下:


In [11]:
r = requests.get("http://httpbin.org/get")
print('type(r.text) : ', type(r.text), '\n')
print('r.json() : ', r.json(), '\n')
print('type(r.json()) : ', type(r.json()), '\n')


type(r.text) :  <class 'str'> 

r.json() :  {'headers': {'Accept': '*/*', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.9.1', 'Accept-Encoding': 'gzip, deflate'}, 'url': 'http://httpbin.org/get', 'args': {}, 'origin': '120.236.174.193'} 

type(r.json()) :  <class 'dict'> 

但注意,如果返回结果不是Json格式,便会出现解析错误,抛出 json.decoder.JSONDecodeError 的异常。

抓取网页

如上的请求链接返回的是Json形式的字符串,那么如果我们请求普通的网页,那么肯定就能获得相应的内容了。

下面我们以知乎-发现页面为例来体验一下:


In [12]:
import requests
import re

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
r = requests.get("https://www.zhihu.com/explore", headers=headers)
pattern = re.compile('explore-feed.*?question_link.*?>(.*?)</a>', re.S)
titles = re.findall(pattern, r.text)
print(titles)


['\n你是从什么时候开始从暴白变成暴黑的?\n', '\n一些病原体是如何做到操控宿主行为的?\n', '\n金庸笔下哪些人物的结局细思极有深意?\n', '\n从小学到高中你最喜欢的语文课文是哪一篇?\n', '\n你们见过的运气最好的人是什么样的?\n', '\n如何评价尤文图斯 2017 年新队徽?\n', '\n在美国持opt或h1b工作期间交的的养老金 (401k) 如果今后长期回国了,会被如何处置?\n', '\nQQ上发送么么哒时候,弹出弹跳表情,是如何实现的?\n', '\n如何评价萨德的文学在哲学上的影响?\n', '\n如何評價霍尊的《卷珠帘》?\n']

如上代码,我们请求了知乎-发现页面 https://www.zhihu.com/explore ,在这里加入了头信息,头信息中包含了 User-Agent 信息,也就是上一节提到的浏览器标识信息。如果不加这个,知乎会禁止抓取。可以看到,我们成功提取出了所有的问题内容。

抓取二进制数据

在上面的例子中,我们抓取的是知乎的一个页面,实际上它返回的是一个HTML文档,那么如果我们想抓去图片、音频、视频等文件的话应该怎么办呢? 我们都知道,图片、音频、视频这些文件都是本质上由二进制码组成的,由于有特定的保存格式和对应的解析方式,我们才可以看到这些形形色色的多媒体。所以想要抓取他们,那就需要拿到他们的二进制码。

下面我们以GitHub的站点图标,也就是在浏览器每一个标签上显示的小图标,为例来感受一下:


In [13]:
r = requests.get("https://github.com/favicon.ico")
print(r.text)
print(r.content)


8���
Y��������������Y��������������������^^������������������������������������������������������������������������bb������g������������g������__������������55������4�����2((2�����4�����\c����������c\�������������������������������3������������������������3B����������������������B1��������������������1������������������1��������������1c��������c
b'\x00\x00\x01\x00\x02\x00\x10\x10\x00\x00\x01\x00 \x00(\x05\x00\x00&\x00\x00\x00  \x00\x00\x01\x00 \x00(\x14\x00\x00N\x05\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x13v\x13\x13\x13\xc5\x0e\x0e\x0e\x12\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x11\x11\x11\x14\xb1\x13\x13\x13i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x14\x14\x96\x13\x13\x14\xfc\x13\x13\x14\xed\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x13\x85\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x13\xc1\x13\x13\x14\xee\x11\x11\x11\x1e\x0f\x0f\x0f\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\x13\x13\x14\xf5\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x14\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x14\x14\x99\x15\x15\x17\xff\x05\x05\x11,\r\r\r\\\x0e\x0e\x0f\xc1\x0f\x0f\x0f"\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x0e\x0e4\x10\x10\x10\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\x8f\x00\x00\x00\x00\x0f\x0f\x0f0\x0f\r\x0f\xff\x00\x00\x00\xf9\x01\x01\x01\xed\x02\x02\x02\xff\x02\x02\x02\xf6\r\r\r8\x00\x00\x00\x00\x00\x00\x00\x00\x07\x07\x07@\x02\x02\x02\xeb\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x11-\x13\x13\x16\x9c\x14\x14\x15\xff\x01\x01\x01\xfc\x0f\x0f\x11\xfb\x0c\x0c\x11;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\r\x11:\x13\x13\x14\xe7\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\x9a\x13\x13\x13\xd9\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13O\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10L\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\xda\x13\x13\x14\xf6\x15\x15\x17\xff\x14\x14\x14\xf0\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x13\x13\x14\xf1\x15\x15\x17\xff\x13\x13\x14\xf6\x13\x13\x14\xf7\x15\x15\x17\xff\x14\x14\x14\xe1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x14\x14\xe1\x15\x15\x17\xff\x13\x13\x14\xf7\x13\x13\x14\xde\x15\x15\x17\xff\x13\x13\x14\xf9\x0f\x0f\x0f!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10\x1f\x13\x13\x14\xf8\x15\x15\x17\xff\x13\x13\x14\xde\x11\x11\x14\xa2\x15\x15\x17\xff\x15\x15\x17\xff\x0e\x0e\x0e4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f@\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x14\xa2\r\r\r8\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12\x98\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x00\x12\x12\x12\x98\x15\x15\x17\xff\x15\x15\x17\xff\r\r\r8\x00\x00\x00\x00\x11\x11\x14\xa4\x15\x15\x17\xff\x11\x11\x13\xc1\x0e\x0e\x0e6\x00\x00\x00\x81\r\r\r\xdc\x12\x12\x14\xd8\x12\x12\x14\xd8\x13\x13\x14\xf7\x00\x00\x00t\x04\x04\x047\x11\x11\x13\xc1\x15\x15\x17\xff\x11\x11\x14\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x13\x13\x13\xc6\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\xc6\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x11\x11\x14\xa2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x14\xa2\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10>\x12\x12\x12\x97\x13\x13\x13\xd9\x12\x12\x14\xf2\x12\x12\x14\xf2\x13\x13\x13\xd9\x12\x12\x12\x97\x10\x10\x10>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x11\x11\x13s\x13\x13\x13\xda\x13\x13\x14\xec\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x13\x13\x14\xec\x13\x13\x13\xda\x11\x11\x13t\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x11\x14d\x13\x13\x14\xea\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0f\x0f\x0f\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x10\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xeb\x11\x11\x14e\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x0e\x0e\x12\x13\x13\x13\xb7\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0f\x0f\x0f\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x10\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\xb7\x0e\x0e\x0e\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10\x1f\x13\x13\x14\xdb\x15\x15\x17\xff\x15\x15\x17\xff\x14\x14\x14\xc3\x11\x11\x13u\x0f\x0f\x0f`\x13\x13\x13x\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x10\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xdb\x10\x10\x10\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x13\x13\x14\xdc\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12o\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x10\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xdc\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x13\x13\x13\xc4\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xb9\x00\x00\x00\x00\x0f\x0f\x0f\x10\x0f\x0f\x0fc\x12\x12\x12z\x0e\x0e\x0eF\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x0c\x0c\x15\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\xc4\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x12\x12~\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\r\r\r8\x0f\x0f\x0f!\x13\x13\x13\xe2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x11<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x10\x10>\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12~\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x11\x1e\x13\x13\x14\xf7\x15\x15\x17\xff\x13\x13\x14\xfe\x11\x11\x13s\x00\x00\x00\x07\x13\x13\x14\xc9\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xae\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x11\x14\xb0\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf7\x11\x11\x11\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x12\x12\x12\x97\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12\x8a\x10\x10\x10?\x11\x11\x13\xc2\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xfa\x13\x13\x16\xaa\x11\x11\x14e\x0e\x0e\x0e4\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\r\r\x119\x0e\x0e\x13h\x13\x13\x14\xae\x13\x13\x14\xfa\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12\x97\x00\x00\x00\x00\x00\x00\x00\r\x13\x13\x14\xf5\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xab\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x13\x13\x14\xab\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf5\x00\x00\x00\r\x0e\x0e\x14Y\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\x8f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x13\x13\x8f\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0e\x0e\x14Y\x13\x13\x13\x9d\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x14\xd1\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x11\x11\x14\xd1\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\x9d\x11\x11\x14\xd0\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x12\x12^\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x11\x11\x14\xd0\x12\x12\x14\xf2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x00\x00\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x14\xf2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x14\xf2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x12\x14\xf2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xdb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x13\x14\xdc\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf6\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x14\x14\x14\xe1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x14\x14\xe1\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf6\x13\x13\x14\xd6\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xfc\x11\x11\x11\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x11\x0f\x13\x13\x14\xfc\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xd6\x13\x13\x13\xa9\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0f\x0f\x0fb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0fb\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\xa9\x0e\x0e\x13g\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x16\xe3\x0e\x0e\x0e\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x0e\x0e\x12\x13\x13\x13\xe2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0e\x0e\x13g\x00\x00\x00\x18\x13\x13\x14\xfc\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x12\x12\x12_\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x12\x12_\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xfc\x00\x00\x00\x18\x00\x00\x00\x00\x13\x13\x14\xae\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0e\x0e\x0e5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x0e\x0e5\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xae\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x0e\x0e4\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0f\x0f\x0f2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x11\x0f\x0c\x0c\x0c(\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x0c\x0c\x0c(\x11\x11\x11\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f2\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x0e\x0e\x0e4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x13\x14\x9e\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x13\\\x00\x00\x00\x00\x00\x00\x00\x07\x0f\x0f\x0fc\x13\x13\x14\xe8\x15\x15\x17\xff\x13\x13\x14\xf3\x14\x14\x14\xd2\x11\x11\x13\xc1\x11\x11\x13\xc1\x14\x14\x14\xd2\x13\x13\x14\xf3\x15\x15\x17\xff\x13\x13\x14\xe8\x0f\x0f\x0fc\x00\x00\x00\x07\x00\x00\x00\x00\x13\x13\x13\\\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\x9e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x11\x13\x13\x14\xdf\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xd6\x13\x13\x14\xad\x13\x13\x14\xf1\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf1\x13\x13\x14\xad\x13\x13\x14\xd6\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xdf\x0f\x0f\x0f\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f3\x13\x13\x14\xf1\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf1\x0f\x0f\x0f3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0fB\x13\x13\x14\xf1\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf1\x0f\x0f\x0fB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f1\x13\x13\x14\xde\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xde\x0f\x0f\x0f1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11\x11\x0f\x13\x13\x13\x9b\x13\x13\x14\xfe\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xfe\x13\x13\x13\x9b\x11\x11\x11\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f1\x13\x13\x13\xa9\x13\x13\x14\xfb\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xfb\x13\x13\x13\xa9\x0f\x0f\x0f1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x0c\x0c\x14\x0f\x0f\x0fc\x11\x11\x14\xa4\x14\x14\x14\xd2\x13\x13\x14\xf3\x15\x15\x17\xff\x15\x15\x17\xff\x13\x13\x14\xf3\x14\x14\x14\xd2\x11\x11\x14\xa4\x0f\x0f\x0fc\x0c\x0c\x0c\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

在这里打印了 response 的两个属性,一个是 text,另一个是 content 。前两行便是r.text的结果,最后一行是r.content的结果。

可以注意到,前者出现了乱码,后者结果前面带有一个b,代表这是bytes类型的数据。由于图片是二进制数据,所以前者在打印时转化为str类型,也就是图片直接转化为字符串,理所当然会出现乱码。

两个属性有什么区别?前者返回的是字符串类型,如果返回结果是文本文件,那么用这种方式直接获取其内容即可。如果返回结果是图片、音频、视频等文件,requests会为我们自动解码成bytes类型,即获取字节流数据。

进一步地,我们可以将刚才提取到的图片保存下来。


In [14]:
with open('data/favicon.ico', 'wb') as f:
    f.write(r.content)
    f.close()

在这里用了open() 函数,第一个参数是文件名称,第二个参数代表以二进制写的形式打开,可以向文件里写入二进制数据,然后保存。 运行结束之后,可以发现在data文件夹中出现了名为favicon.ico的图标。

添加头信息

urllib.request一样,我们也可以通过headers参数来传递头信息。你可以在headers这个数组中任意添加其他的头信息。

比如上面的知乎的例子,如果不传递头信息,就不能正常请求:


In [15]:
r = requests.get("https://www.zhihu.com/explore")
print(r.text)


<html><body><h1>500 Server Error</h1>
An internal server error occured.
</body></html>

基本POST请求

在前面我们讲解了最基本的 GET 请求,另外一种比较常见的请求方式就是 POST 了,就像模拟表单提交一样,将一些数据提交到某个链接。

使用 requests 实现 POST 请求同样非常简单,下面的例子请求的是httpbin.org/post,它可以判断如果请求是POST方式,就把相关请求信息输出出来。


In [16]:
import requests

data = {'name': 'germey', 'age': '22'}
r = requests.post("http://httpbin.org/post", data=data)
print(r.text)


{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "age": "22", 
    "name": "germey"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "18", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/post"
}

可以发现,成功获得了返回结果,返回结果中的form部分就是提交的数据,那么这就证明POST请求成功发送了。

响应

发送请求之后,得到的自然就是响应,在上面的实例中我们使用了textcontent获取了响应内容。不过还有很多属性和方法可以获取其他的信息。比如响应状态码、响应头、Cookies。

下面用一个实例来感受一下:


In [17]:
r = requests.get('http://www.jianshu.com')
print(type(r.status_code), r.status_code)
print(type(r.headers), r.headers)
print(type(r.cookies), r.cookies)
print(type(r.url), r.url)
print(type(r.history), r.history)


<class 'int'> 200
<class 'requests.structures.CaseInsensitiveDict'> {'X-Runtime': '0.009434', 'Set-Cookie': '_session_id=bnovRTVNMVBwNlliNlUvNHlnOW5MUFg4a0hwVlJJM0VTeS83emJBV0FBYWpzc3RRR1dQcWM2NGxCcjU3c2c0YnE0NlVTOTA0TStzTlUybEFjT2M2V1MxTkJiR1lEbitYdXZPamdZNDBBeVJXSWNXaEVWaEJSVDl2YnJqZTNmZFM2b3lSNllSM09nNmtTLzFQUEdtOVlGUkkwZVhiSWZTWkJNSWUzNGIwSUZEbWh1a0ZLTWVqdWJDZTVPVmxTZTRGMm4wYi85b3BkanhCbnAwTXgyd2RsVGpPUzl6dS8rZEN4SmJ1MDE5bFZkb1o4cXVhT0pESFpLUlpCdHJVVzlrKy0tNTdJMnVTQVZpQ0g0YWJCYVBpZ3NBQT09--cece1d17c770a7f06fc8999491b56354d31106b4; path=/; HttpOnly', 'Cache-Control': 'max-age=0, private, must-revalidate', 'Connection': 'keep-alive', 'X-Content-Type-Options': 'nosniff', 'Content-Encoding': 'gzip', 'X-XSS-Protection': '1; mode=block', 'Vary': 'Accept-Encoding', 'Transfer-Encoding': 'chunked', 'Date': 'Sat, 18 Feb 2017 15:45:43 GMT', 'Content-Type': 'text/html; charset=utf-8', 'ETag': 'W/"9af6928298780dd2b3ad8fcd068388f5"', 'X-Request-Id': '9f18b0d2-626f-4ecb-a682-e2d39b7cddaf', 'Server': 'Tengine', 'X-Frame-Options': 'DENY'}
<class 'requests.cookies.RequestsCookieJar'> <RequestsCookieJar[<Cookie _session_id=bnovRTVNMVBwNlliNlUvNHlnOW5MUFg4a0hwVlJJM0VTeS83emJBV0FBYWpzc3RRR1dQcWM2NGxCcjU3c2c0YnE0NlVTOTA0TStzTlUybEFjT2M2V1MxTkJiR1lEbitYdXZPamdZNDBBeVJXSWNXaEVWaEJSVDl2YnJqZTNmZFM2b3lSNllSM09nNmtTLzFQUEdtOVlGUkkwZVhiSWZTWkJNSWUzNGIwSUZEbWh1a0ZLTWVqdWJDZTVPVmxTZTRGMm4wYi85b3BkanhCbnAwTXgyd2RsVGpPUzl6dS8rZEN4SmJ1MDE5bFZkb1o4cXVhT0pESFpLUlpCdHJVVzlrKy0tNTdJMnVTQVZpQ0g0YWJCYVBpZ3NBQT09--cece1d17c770a7f06fc8999491b56354d31106b4 for www.jianshu.com/>]>
<class 'str'> http://www.jianshu.com/
<class 'list'> []

在这里分别打印输出了响应状态吗status_code,响应头headersCookies,请求连接,请求历史的类型和内容。可以看到,headers还有cookies这两个部分都是特定的数据结构,打开浏览器同样可以发现有同样的响应头信息。

状态码

在这里状态码常用来判断请求是否成功,requests还提供了一个内置的状态码查询对象requests.codes。比如你可以通过if r.status_code == requests.codes.ok来判断请求是否成功。


In [18]:
r = requests.get('http://www.jianshu.com')
exit() if not r.status_code == requests.codes.ok else print('Request Successfully')


Request Successfully

在这里,通过比较返回码和内置的成功的返回码是一致的,来保证请求得到了正常响应,输出成功请求的消息,否则程序终止。

那么肯定不能只有ok这个条件码,还有没有其他的呢?答案是肯定的。下面列出了返回码和相应的查询条件:

# Informational.
    100: ('continue',),
    101: ('switching_protocols',),
    102: ('processing',),
    103: ('checkpoint',),
    122: ('uri_too_long', 'request_uri_too_long'),
    200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'),
    201: ('created',),
    202: ('accepted',),
    203: ('non_authoritative_info', 'non_authoritative_information'),
    204: ('no_content',),
    205: ('reset_content', 'reset'),
    206: ('partial_content', 'partial'),
    207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'),
    208: ('already_reported',),
    226: ('im_used',),

    # Redirection.
    300: ('multiple_choices',),
    301: ('moved_permanently', 'moved', '\\o-'),
    302: ('found',),
    303: ('see_other', 'other'),
    304: ('not_modified',),
    305: ('use_proxy',),
    306: ('switch_proxy',),
    307: ('temporary_redirect', 'temporary_moved', 'temporary'),
    308: ('permanent_redirect',
          'resume_incomplete', 'resume',), # These 2 to be removed in 3.0

    # Client Error.
    400: ('bad_request', 'bad'),
    401: ('unauthorized',),
    402: ('payment_required', 'payment'),
    403: ('forbidden',),
    404: ('not_found', '-o-'),
    405: ('method_not_allowed', 'not_allowed'),
    406: ('not_acceptable',),
    407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'),
    408: ('request_timeout', 'timeout'),
    409: ('conflict',),
    410: ('gone',),
    411: ('length_required',),
    412: ('precondition_failed', 'precondition'),
    413: ('request_entity_too_large',),
    414: ('request_uri_too_large',),
    415: ('unsupported_media_type', 'unsupported_media', 'media_type'),
    416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'),
    417: ('expectation_failed',),
    418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'),
    421: ('misdirected_request',),
    422: ('unprocessable_entity', 'unprocessable'),
    423: ('locked',),
    424: ('failed_dependency', 'dependency'),
    425: ('unordered_collection', 'unordered'),
    426: ('upgrade_required', 'upgrade'),
    428: ('precondition_required', 'precondition'),
    429: ('too_many_requests', 'too_many'),
    431: ('header_fields_too_large', 'fields_too_large'),
    444: ('no_response', 'none'),
    449: ('retry_with', 'retry'),
    450: ('blocked_by_windows_parental_controls', 'parental_controls'),
    451: ('unavailable_for_legal_reasons', 'legal_reasons'),
    499: ('client_closed_request',),

    # Server Error.
    500: ('internal_server_error', 'server_error', '/o\\', '✗'),
    501: ('not_implemented',),
    502: ('bad_gateway',),
    503: ('service_unavailable', 'unavailable'),
    504: ('gateway_timeout',),
    505: ('http_version_not_supported', 'http_version'),
    506: ('variant_also_negotiates',),
    507: ('insufficient_storage',),
    509: ('bandwidth_limit_exceeded', 'bandwidth'),
    510: ('not_extended',),
    511: ('network_authentication_required', 'network_auth', 'network_authentication'),

比如如果你想判断结果是不是404状态,你可以用requests.codes.not_found来比对。

响应头

如果想得到响应头信息,可以使用headers属性。它其实本质上也是一个字典形式。可以通过数组索引或者get()方法来获取某一条头信息内容。 比如获取Content-Type可以用r.headers['Content-Type'],也可以用r.headers.get('content-type')

文件上传

我们知道reqeuests可以模拟提交一些数据,假如有的网站需要我们上传文件,我们同样可以利用它来上传,实现非常简单。

在上面一节中我们下载保存了一个文件叫做favicon.ico,这次我们用它为例来模拟文件上传的过程。


In [19]:
files = {'file': open('data/favicon.ico', 'rb')}
r = requests.post("http://httpbin.org/post", files=files)
print(r.text)


{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "data:application/octet-stream;base64,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F/8VFRf/FRUX/xMTFKsAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRMTFKsVFRf/FRUX/xUVF/8VFRf/FRUX/xUVF/8TExT1AAAADQ4OFFkVFRf/FRUX/xUVF/8VFRf/FRUX/xUVF/8TExOPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMTE48VFRf/FRUX/xUVF/8VFRf/FRUX/xUVF/8ODhRZExMTnRUVF/8VFRf/FRUX/xUVF/8VFRf/EREU0QAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBERFNEVFRf/FRUX/xUVF/8VFRf/FRUX/xMTE50RERTQFRUX/xUVF/8VFRf/FRUX/xUVF/8SEhJeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEhISXhUVF/8VFRf/FRUX/xUVF/8VFRf/EREU0BISFPIVFRf/FRUX/xUVF/8VFRf/FRUX/wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFRUX/xUVF/8VFRf/FRUX/xUVF/8SEhTyFRUX/xUVF/8VFRf/FRUX/xUVF/8SEhTyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASEhTyFRUX/xUVF/8VFRf/FRUX/xUVF/8VFRf/FRUX/xUVF/8VFRf/FRUX/xMTFNsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMTFNwVFRf/FRUX/xUVF/8VFRf/FRUX/xMTFPYVFRf/FRUX/xUVF/8VFRf/FBQU4QAA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AAAAAAAADAwMFA8PD2MRERSkFBQU0hMTFPMVFRf/FRUX/xMTFPMUFBTSEREUpA8PD2MMDAwUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "6665", 
    "Content-Type": "multipart/form-data; boundary=e4cbb78ae09e4aaeb006970efd960136", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "origin": "120.236.174.193", 
  "url": "http://httpbin.org/post"
}

这个网站会返回一个响应,里面包含files这个字段,而form是空的,这证明文件上传部分,会单独有一个files来标识。

Cookie处理

在前面我们使用了urllib,让它处理cookie真的是挺麻烦的,而有了requests,获得和提交cookies只需要一步。我们先用一个实例感受一下获取Cookie的过程:


In [20]:
import requests

r = requests.get("https://www.baidu.com")
print(r.cookies)
for key, value in r.cookies.items():
    print(key + '=' + value)


<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>, <Cookie __bsi=2045780261471239428_00_135_N_N_5_0303_C02F_N_N_N_0 for .www.baidu.com/>]>
BDORZ=27315
__bsi=2045780261471239428_00_135_N_N_5_0303_C02F_N_N_N_0

可以看到,首先打印输出了cookie,可以发现它是一个RequestCookieJar类型。然后用items()方法将其转化为元组组成的列表,遍历输出每一个cookie的名和值。

当然,我们也可以直接用Cookie来维持登录状态。比如我们以知乎为例,直接利用Cookie来维持登录状态。

首先登录知乎,将请求头中的Cookie复制下来。

(知乎已经更改了登陆方式,现在使用Cookie无法登陆)


In [21]:
headers = {
    'Cookie': '_za=dc07d0bb-599c-46e9-8906-f6dd252910b4; d_c0="AIAABz1hvQmPTup3qtT92xkZN2UQoova_cc=|1460107885"; _zap=3c9b8860-2a38-4532-b476-c3617ff3fb0d; _ga=GA1.2.1945944829.1442545470; aliyungf_tc=AQAAANoM4BIxkAMAj67seLZyZFoQgALT; q_c1=a366104786da4623b23af9cd321e4d38|1484577173000|1468254315000; _xsrf=b9564d003dd4bdb7b6f9e6185b8a0b78; l_cap_id="MTZlMjVmODgwYTVlNGEyYzg1ZDBkNzhkMzNjYjMxYmI=|1484577173|1c7374494b0e1a7ef526ea93c7065b2a8b9736eb"; cap_id="MzU3OGUzZjYwYjIwNGNmNWFhMTk2OGU2NjRjOWE3MDk=|1484577173|b5723f8256e35bd66f86d1e070c3a3d4324c655a"; r_cap_id="YmQwYmEwNDIxMDYxNDBkZmI2NzAzNjI2ZjJkMzNmOGQ=|1484577175|01cabbd0c7a481a7e4a907ae60ba3e2c64d07ddc"; login="NWVhMDVlNzZjMzI0NGE3ZGIyMmExODFhNzEzNGVhNmY=|1484577185|45503ef9b8dc4c3468f776c202fbc7fe442f8521"; n_c=1; z_c0=Mi4wQUFDQXhFMGpBQUFBZ0FBSFBXRzlDUmNBQUFCaEFsVk5vV2FrV0FBQkU5RmpvbXljZE15a2FZNU8zQVRjS0g1Qm1n|1484577189|3dc63f1a6bd389c32162f4d901ebf10e6750dffc; nweb_qa=heifetz; __utma=51854390.1945944829.1442545470.1484577176.1484577176.1; __utmb=51854390.0.10.1484577176; __utmc=51854390; __utmz=51854390.1484577176.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=51854390.100-1|2=registration_date=20140101=1^3=entry_date=20140101=1',
    'Host': 'www.zhihu.com',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
}
r = requests.get("http://www.zhihu.com", headers=headers)
print(r.text)


<!DOCTYPE html>
<html lang="zh-CN" class="">
<head>
<meta charset="utf-8">
<meta name="apple-itunes-app" content="app-id=432274380">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit" />
<meta name="description" content="一个真实的网络问答社区,帮助你寻找答案,分享知识。"/>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
<title>知乎 - 与世界分享你的知识、经验和见解</title>



<link rel="apple-touch-icon" href="https://static.zhihu.com/static/revved/img/ios/touch-icon-152.87c020b9.png" sizes="152x152">
<link rel="apple-touch-icon" href="https://static.zhihu.com/static/revved/img/ios/touch-icon-120.496c913b.png" sizes="120x120">
<link rel="apple-touch-icon" href="https://static.zhihu.com/static/revved/img/ios/touch-icon-76.dcf79352.png" sizes="76x76">
<link rel="apple-touch-icon" href="https://static.zhihu.com/static/revved/img/ios/touch-icon-60.9911cffb.png" sizes="60x60">

<link rel="shortcut icon" href="https://static.zhihu.com/static/favicon.ico" type="image/x-icon" />
<link rel="dns-prefetch" href="p1.zhimg.com"/>
<link rel="dns-prefetch" href="p2.zhimg.com"/>
<link rel="dns-prefetch" href="p3.zhimg.com"/>
<link rel="dns-prefetch" href="p4.zhimg.com"/>
<link rel="dns-prefetch" href="comet.zhihu.com"/>
<link rel="dns-prefetch" href="static.zhihu.com"/>
<link rel="dns-prefetch" href="upload.zhihu.com"/>
<link rel="stylesheet" href="https://static.zhihu.com/static/revved/-/css/pages/unlogin-index/main.e87dad73.css">
<meta name="google-site-verification" content="FTeR0c8arOPKh8c5DYh_9uu98_zJbaWw53J-Sch9MTg" />
<meta name="baidu-site-verification" content="KPFppAFoYF4Kkdv9" />
<meta property="qc:admins" content="00544670776201056375" />
<link rel="canonical" href="http://www.zhihu.com" />
<meta id="znonce" name="znonce" content="62d12ae8910d4442b167671143c8dce6">
<!--[if lt IE 9]>
<script src="https://static.zhihu.com/static/components/respond/dest/respond.min.js"></script>
<link href="https://static.zhihu.com/static/components/respond/cross-domain/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />
<link href="/static/components/respond/cross-domain/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />
<script src="/static/components/respond/cross-domain/respond.proxy.js"></script>
<![endif]-->
<script src="https://static.zhihu.com/static/revved/-/js/instant.14757a4a.js"></script>
</head>
<body class="zhi ">



<div class="index-main">
<div class="index-main-body">
<div class="index-header">

<h1 class="logo hide-text">知乎</h1>

<h2 class="subtitle">与世界分享你的知识、经验和见解</h2>
</div>

<div class="desk-front sign-flow clearfix sign-flow-simple">

<div class="index-tab-navs">
<div class="navs-slider">
<a href="#signup" class="active">注册</a>
<a href="#signin">登录</a>
<span class="navs-slider-bar"></span>
</div>
</div>


<div class="view view-signin" data-za-module="SignInForm">
<form method="POST">
<input type="hidden" name="_xsrf" value="e2081d361a726a8d752554e5583a1756"/>
<div class="group-inputs">

<div class="account input-wrapper">

<input type="text" name="account" aria-label="手机号或邮箱" placeholder="手机号或邮箱" required>
</div>
<div class="verification input-wrapper">
<input type="password" name="password" aria-label="密码" placeholder="密码" required /><button type="button" class="send-code-button">获取验证码</button>
</div>

<div class="input-wrapper captcha-module" data-type="en" >
<input id="captcha" name="captcha" placeholder="验证码" required data-rule-required="true" data-msg-required="请填写验证码">
<div class="captcha-container">

<img class="js-refreshCaptcha captcha" width="120" height="30" data-tooltip="s$t$看不清楚?换一张"  alt="验证码">
</div>
</div>

</div>
<div class="button-wrapper command">
<button class="sign-button submit" type="submit">登录</button>
</div>
<div class="signin-misc-wrapper clearfix">

<button type="button" class="signin-switch-button">手机验证码登录</button>

<a class="unable-login" href="#">无法登录?</a>
</div>

<div class="social-signup-wrapper" data-za-module="SNSSignIn">
<span class="name js-toggle-sns-buttons">社交帐号登录</span>

<div class="sns-buttons">
<a title="微信登录" class="js-bindwechat" href="#"><i class="sprite-index-icon-wechat"></i></a>
<a title="微博登录" class="js-bindweibo" href="#"><i class="sprite-index-icon-weibo"></i></a>
<a title="QQ 登录" class="js-bindqq" href="#"><i class="sprite-index-icon-qq"></i></a>
</div>


</div>

</form>

<div class="QRCode">
<button class="QRCode-toggleButton">
<span class="sprite-global-icon-qrcode"></span>
<span class="QRCode-toggleButtonText ">下载知乎 App</span>
</button>
<div class="QRCode-card">
<div class="QRCode-image"></div>
<div class="sprite-index-icon-arrow"></div>
</div>
</div>


</div>
<div class="view view-signup selected" data-za-module="SignUpForm">
<form class="zu-side-login-box" action="/register/email" id="sign-form-1" autocomplete="off" method="POST">
<input type="password" hidden> 
<input type="hidden" name="_xsrf" value="e2081d361a726a8d752554e5583a1756"/>
<div class="group-inputs">


<div class="name input-wrapper">
<input required type="text" name="fullname" aria-label="姓名" placeholder="姓名">
</div>
<div class="email input-wrapper">

<input required type="text" class="account" name="phone_num" aria-label="手机号(仅支持中国大陆)" placeholder="手机号(仅支持中国大陆)">

</div>

<div class="input-wrapper">
<input required type="password" name="password" aria-label="密码" placeholder="密码(不少于 6 位)" autocomplete="off">
</div>

<div class="Captcha input-wrapper" data-type="cn" data-za-module="Captcha">
<div class="Captcha-operate">
<input type="hidden" name="captcha" required data-rule-required="true" data-msg-required="请点击图中所有倒立的文字">
<input type="hidden" name="captcha_type" value="cn" required>
<label class="Captcha-prompt">请点击图中所有倒立的文字</label>
<span class="Captcha-refresh js-refreshCaptcha sprite-index-icon-refresh"></span>
</div>
<div class="Captcha-imageConatiner">
<img class="Captcha-image" alt="验证码" >
</div>
</div>

</div>
<div class="button-wrapper command">
<button class="sign-button submit" type="submit">注册知乎</button>
</div>
</form>

<p class="agreement-tip">点击「注册」按钮,即代表你同意<a href="/terms" target="_blank">《知乎协议》</a></p>

<div class="QRCode">
<button class="QRCode-toggleButton">
<span class="sprite-global-icon-qrcode"></span>
<span class="QRCode-toggleButtonText ">下载知乎 App</span>
</button>
<div class="QRCode-card">
<div class="QRCode-image"></div>
<div class="sprite-index-icon-arrow"></div>
</div>
</div>



</div>
</div>
</div>

</div>
<div class="footer">

<span>&copy; 2017 知乎</span>
<span class="dot">·</span>
<a target="_blank" href="/roundtable">知乎圆桌</a>
<span class="dot">·</span>
<a target="_blank" href="/explore" data-za-c="explore" data-za-a="visit_explore" data-za-l="home_bottom_explore">发现</a>
<span class="dot">·</span>
<a target="_blank" href="/app">移动应用</a>
<span class="dot">·</span>


<a href="/org/signin" class="footer-mobile-show">使用机构帐号登录</a>

<span class="dot footer-mobile-show">·</span>

<a href="/contact" class="footer-mobile-show">联系我们</a>
<span class="dot">·</span>
<a target="_blank" href="/careers">来知乎工作</a>
<br />
<a href="http://www.miibeian.gov.cn/" target="_blank">京 ICP 证 110745 号</a>
<span class="dot">·</span>
<span>京公网安备 11010802010035 号</span>
<span class="dot">·</span>
<a href="http://zhstatic.zhihu.com/assets/zhihu/publish-license.jpg" target="_blank">出版物经营许可证</a>

</div>



<script type="text/json" class="json-inline" data-name="disabled_components">["back_to_top"]</script>
<script type="text/json" class="json-inline" data-name="current_user">["","","","-1","",0,0]</script>
<script type="text/json" class="json-inline" data-name="env">["zhihu.com","comet.zhihu.com",false,null,false,false]</script>

<script type="text/json" class="json-inline" data-name="ga_vars">{"user_created":0,"now":1487432747000,"abtest_mask":"------------------------------","user_attr":[0,0,0,"-","-"],"user_hash":0}</script>

<script src="https://static.zhihu.com/static/revved/-/js/vendor.cb14a042.js"></script>
<script src="https://static.zhihu.com/static/revved/-/js/closure/base.84f61660.js"></script>

<script src="https://static.zhihu.com/static/revved/-/js/closure/common.9ec832a9.js"></script>
<script src="https://static.zhihu.com/static/revved/-/js/closure/page-index.4c5acdf0.js"></script>
<meta name="entry" content="ZH.entrySignPage" data-module-id="page-index">


<input type="hidden" name="_xsrf" value="e2081d361a726a8d752554e5583a1756"/>
</body>
</html>

会话维持

requests中,我们如果直接利用requests.get()requests.post()等方法的确可以做到模拟网页的请求。但是这实际上是相当于不同的会话,即不同的session,也就是说相当于你用了两个浏览器打开了不同的页面。

设想这样一个场景,你第一个请求利用了requests.post()方法登录了某个网站,第二次想获取成功登录后的自己的个人信息,你又用了一次requests.get()方法。实际上,这相当于打开了两个浏览器,是两个完全不相关的会话,你说你能成功获取个人信息吗?那当然不能。

有小伙伴就说了,我在两次请求的时候都设置好一样的Cookie不就行了?行是行,但是不觉得麻烦吗?每次都要这样。是我我忍不了。其实解决这个问题的主要方法就是维持同一个会话,也就是相当于打开一个新的浏览器选项卡而不是新开一个浏览器。但是我又不想每次设置Cookie,那该咋办?这时候就有了新的利器Session。利用它,我们可以方便地维护一个会话,而且不用担心Cookie的问题,它会帮我们自动处理好。

在下面的实例中我们请求了一个测试网址,http://httpbin.org/cookies/set/number/123456789请求这个网址我们可以设置Cookie,名称叫做number,内容是123456789,后面的网址http://httpbin.org/cookies可以获取当前的Cookie

你觉得这样能成功获取到设置的Cookie吗?运行结果如下:


In [22]:
requests.get('http://httpbin.org/cookies/set/number/123456789')
r = requests.get('http://httpbin.org/cookies')
print(r.text)


{
  "cookies": {}
}

并不行。那这时候我们想起刚才说的Session了,改成这个试试看:


In [23]:
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)


{
  "cookies": {
    "number": "123456789"
  }
}

成功获取!所以,利用Session我们可以做到模拟同一个会话,而且不用担心Cookie的问题,通常用于模拟登录成功之后再进行下一步的操作。

Session在平常用到的非常广泛,可以用于模拟在一个浏览器中打开同一站点的不同页面。

SSL证书验证

reqeusts 提供了证书验证的功能,当一个请求是 https 的时候,它会检查 SSL 证书,可以使用 verify 这个参数。(其实如果不加的话默认是True,会自动验证的)

现在以12306( https://www.12306.cn)为例来感受一下它的用法,我们现在访问它都可以看到一个证书问题的页面,如下:

现在我们用requests来测试一下:


In [24]:
import requests

response = requests.get('https://www.12306.cn')
print(response.status_code)


---------------------------------------------------------------------------
SSLError                                  Traceback (most recent call last)
/usr/lib/python3/dist-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, **response_kw)
    559                                                   timeout=timeout_obj,
--> 560                                                   body=body, headers=headers)
    561 

/usr/lib/python3/dist-packages/urllib3/connectionpool.py in _make_request(self, conn, method, url, timeout, **httplib_request_kw)
    345         try:
--> 346             self._validate_conn(conn)
    347         except (SocketTimeout, BaseSSLError) as e:

/usr/lib/python3/dist-packages/urllib3/connectionpool.py in _validate_conn(self, conn)
    786         if not getattr(conn, 'sock', None):  # AppEngine might not have  `.sock`
--> 787             conn.connect()
    788 

/usr/lib/python3/dist-packages/urllib3/connection.py in connect(self)
    251                                     server_hostname=hostname,
--> 252                                     ssl_version=resolved_ssl_version)
    253 

/usr/lib/python3/dist-packages/urllib3/util/ssl_.py in ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context, ca_cert_dir)
    304     if HAS_SNI:  # Platform-specific: OpenSSL with enabled SNI
--> 305         return context.wrap_socket(sock, server_hostname=server_hostname)
    306 

/usr/lib/python3.5/ssl.py in wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname)
    376                          server_hostname=server_hostname,
--> 377                          _context=self)
    378 

/usr/lib/python3.5/ssl.py in __init__(self, sock, keyfile, certfile, server_side, cert_reqs, ssl_version, ca_certs, do_handshake_on_connect, family, type, proto, fileno, suppress_ragged_eofs, npn_protocols, ciphers, server_hostname, _context)
    751                         raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
--> 752                     self.do_handshake()
    753 

/usr/lib/python3.5/ssl.py in do_handshake(self, block)
    987                 self.settimeout(None)
--> 988             self._sslobj.do_handshake()
    989         finally:

/usr/lib/python3.5/ssl.py in do_handshake(self)
    632         """Start the SSL/TLS handshake."""
--> 633         self._sslobj.do_handshake()
    634         if self.context.check_hostname:

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)

During handling of the above exception, another exception occurred:

SSLError                                  Traceback (most recent call last)
/usr/lib/python3/dist-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    375                     retries=self.max_retries,
--> 376                     timeout=timeout
    377                 )

/usr/lib/python3/dist-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, **response_kw)
    588             release_conn = True
--> 589             raise SSLError(e)
    590 

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)

During handling of the above exception, another exception occurred:

SSLError                                  Traceback (most recent call last)
<ipython-input-24-44006343c108> in <module>()
      1 import requests
      2 
----> 3 response = requests.get('https://www.12306.cn')
      4 print(response.status_code)

/usr/lib/python3/dist-packages/requests/api.py in get(url, params, **kwargs)
     65 
     66     kwargs.setdefault('allow_redirects', True)
---> 67     return request('get', url, params=params, **kwargs)
     68 
     69 

/usr/lib/python3/dist-packages/requests/api.py in request(method, url, **kwargs)
     51     # cases, and look like a memory leak in others.
     52     with sessions.Session() as session:
---> 53         return session.request(method=method, url=url, **kwargs)
     54 
     55 

/usr/lib/python3/dist-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    466         }
    467         send_kwargs.update(settings)
--> 468         resp = self.send(prep, **send_kwargs)
    469 
    470         return resp

/usr/lib/python3/dist-packages/requests/sessions.py in send(self, request, **kwargs)
    574 
    575         # Send the request
--> 576         r = adapter.send(request, **kwargs)
    577 
    578         # Total elapsed time of the request (approximately)

/usr/lib/python3/dist-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    445         except (_SSLError, _HTTPError) as e:
    446             if isinstance(e, _SSLError):
--> 447                 raise SSLError(e, request=request)
    448             elif isinstance(e, ReadTimeoutError):
    449                 raise ReadTimeout(e, request=request)

SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)

提示一个错误,叫做SSLError,证书验证错误。

所以如果我们请求一个https站点,但是证书验证错误的页面时,就会报这样的错误,那么如何避免这个错误呢?很简单,把verify这个参数设置为False即可。

改成如下代码:


In [25]:
response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)


/usr/lib/python3/dist-packages/urllib3/connectionpool.py:794: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)
200

不过发现报了一个警告,它提示建议让我们给它指定证书。

当然你可以选择忽略警告:(依旧报出警告)


In [26]:
import requests
from requests.packages import urllib3

urllib3.disable_warnings()
response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)


200
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:794: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)

不过这不是最好的方式,https协议的请求把证书验证都忽略了还有什么意义?

当然你也可以指定一个本地证书用作客户端证书,可以是单个文件(包含密钥和证书)或一个包含两个文件路径的元组。

response = requests.get('https://www.12306.cn', cert=('/path/server.crt', '/path/key'))
print(response.status_code)

上面代码是实例,你需要有crtkey文件,指定它们的路径。注意本地私有证书的key必须要是解密状态,加密状态的key是不支持的。

代理设置

对于某些网站,在测试的时候请求几次,能正常获取内容。但是一旦开始大规模爬取,对于大规模且频繁的请求,网站可能会直接登录验证,验证码,甚至直接把IP给封禁掉。为了防止这种情况的发生,我们就需要设置代理来解决这个问题,需要用到proxies这个参数。

import requests

proxies = {
  "http": "http://10.10.1.10:3128",
  "https": "http://10.10.1.10:1080",
}

requests.get("https://www.taobao.com", proxies=proxies)

当然直接运行这个实例可能不行,因为这个代理可能是无效的,请换成自己的有效代理试验一下。

若你的代理需要使用HTTP Basic Auth,可以使用类似 http://user:password@host/ 这样的语法。

import requests

proxies = {
    "http": "http://user:password@10.10.1.10:3128/",
}
requests.get("https://www.taobao.com", proxies=proxies)

超时设置

在本机网络状况不好或者服务器网络响应太慢甚至无响应时,我们可能会等待特别久的时间才可能会收到一个响应,甚至到最后收不到响应而报错。为了防止服务器不能及时响应,我们应该设置一个超时时间,即超过了这个时间还没有得到响应,那就报错。

设置超时时间需要用到timeout参数。这个时间的计算是发出request请求到服务器响应response的时间。

下面用一个实例来感受一下:


In [27]:
import requests

r = requests.get("https://www.taobao.com", timeout = 1)
print(r.status_code)


200

通过这样的方式,我们可以将超时时间设置为1秒,如果1秒内没有响应,那就抛出异常。

实际上请求分为两个阶段,即连接和读取。上面的设置timeout值将会用作connectread二者的timeout。如果要分别指定,就传入一个元组:


In [28]:
r = requests.get('https://www.taobao.com', timeout=(5, 30))
print(r.status_code)


200

如果想永久等待,那么你可以直接将timeout设置为None,或者不设置,直接留空,因为默认是None。这样的话,如果服务器还在运行,但是响应特别慢,那就慢慢等吧,它永远不会返回超时错误的。

用法如下:


In [29]:
r = requests.get('https://www.taobao.com', timeout=None)
print(r.status_code)


200

或直接不加参数:


In [30]:
r = requests.get('https://www.taobao.com')
print(r.status_code)


200

身份认证

在访问网站时,我们可能会遇到这样的认证页面:

如果遇到这样的网站验证,可以使用requests带的身份认证功能。


In [31]:
import requests
from requests.auth import HTTPBasicAuth

r = requests.get('http://120.27.34.24:9001', auth=HTTPBasicAuth('user', '123'))
print(r.status_code)


200

如果用户名和密码正确的话,认证成功,那么运行结果会返回200,如果认证失败,则会返回401状态码。

当然如果参数都传一个HTTPBasicAuth类,那的确太繁琐了,所以requests提供了一个简单的写法,你可以直接传一个元组,它会默认使用HTTPBasicAuth这个类来认证。

所以上面的代码可以直接简写如下:


In [32]:
import requests

r = requests.get('http://120.27.34.24:9001', auth=('user', '123'))
print(r.status_code)


200

requests还提供了其他的认证方式,如OAuth认证,不过你需要安装oauth包。

pip3 install requests_oauthlib

使用OAuth的方法如下:

import requests
from requests_oauthlib import OAuth1

url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET',
              'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
requests.get(url, auth=auth)

更多详细的功能就可以参考requests_oauthlib的官方文档,在此就不再赘述了。


In [ ]: