python3 requests出错Traceback (most recent call last):

小试牛刀

>>>import requests
>>> r = requests.get('http://www.zhidaow.com')  # 发送请求
>>> r.status_code  # 返回码 
200
>>> r.headers['content-type']  # 返回头部信息
'text/html; charset=utf8'
>>> r.encoding  # 编码信息
'utf-8'
>>> r.text  #内容部分(PS,由于编码问题,建议这里使用r.content)
u'<!DOCTYPE html>\n<html xmlns="http://www.w3.org/1999/xhtml"...'

是不是很简单?比urllib2和urllib简单直观的多?!那请接着看快速指南吧。


快速指南

发送请求

发送请求很简单的,首先要导入requests模块:

>>>import requests

接下来让我们获取一个网页,例如如下url地址:

>>>r = requests.get('http://www.zhidaow.com')

接下来,我们就可以使用这个r的各种方法和函数了。

另外,HTTP请求还有很多类型,比如POST,PUT,DELETE,HEAD,OPTIONS。也都可以用同样的方式实现:

>>> r = requests.get("http://httpbin.org/get") #获取信息
>>> r = requests.post("http://httpbin.org/post") #创建,但是一般在使用的过程中,用来更新,创建,删除都是它
>>> r = requests.put("http://httpbin.org/put") #更新或创建
>>> r = requests.delete("http://httpbin.org/delete") #删除
>>> r = requests.head("http://httpbin.org/get") #获取header信息,和get差不多,只是不返回body数据

这些请求方法按照自己的需要使用。

在URL中传递参数

有时候我们需要在URL中传递参数,比如在采集百度搜索结果时,我们wd参数(搜索词)和rn参数(搜素结果数量),你可以手工组成URL,requests也提供了一种看起来很NB的方法:

#get传递参数
>>> payload = {'wd': '张亚楠', 'rn': '100'}
>>> r = requests.get("http://www.baidu.com/s", params=payload)
>>> print r.urlu'http://www.baidu.com/s?rn=100&wd=%E5%BC%A0%E4%BA%9A%E6%A5%A0'

#post传递dict参数
def post_data():
    data = {"name":"heting", "password":"123456"}
    responce = requests.post("你的url",data=data)
    print(responce.text)
    
#post传递json参数
def post_json():
    params = ["octocat@github.com","support@github.com"] #github api 说明:all data is sent and received as json,如果是其他类型的接口,那么这里按照你们的需求文档来处理
    responce = requests.post(join_url("user/emails"),json=params,auth=("hetingTester","952643152HTan"))
    print(responce.status_code)
    print(json.dumps(responce.json(),indent=4))

上面wd=的乱码就是“张亚楠”的地址栏转码形式。

获取响应内容

可以通过r.text来获取网页的内容,返回字符串。

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

>>> r.text
u'\n

也可以通过r.content来获取页面内容。

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

>>> r.content
b'\n

r.content是以字节的方式去显示

json

像urllib和urllib2,如果用到json,就要引入新模块,如json和simplejson,但在requests中已经有了内置的函数,r.json()。就拿查询IP的API来说:

>>>r = requests.get('http://ip.taobao.com/service/getIpInfo.php?ip=122.88.60.28')
>>>r.json()['data']['country']
'中国'

自定义请求头部

伪装请求头部是采集时经常用的,我们可以用这个方法来隐藏:

r = requests.get('http://www.zhidaow.com')
print r.request.headers['User-Agent']
#python-requests/1.2.3 CPython/2.7.3 Windows/XP

headers = {'User-Agent': 'alexkh'}
r = requests.get('http://www.zhidaow.com', headers = headers)
print r.request.headers['User-Agent']
#alexkh

设置超时时间

你可以告诉 requests 在经过以 timeout 参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。如果不使用,你的程序可能会永远失去响应:

>>> requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)

注意
timeout 仅对连接过程有效,与响应体的下载无关。 timeout 并不是整个下载响应的时间限制,而是如果服务器在 timeout 秒内没有应答,将会引发一个异常(更精确地说,是在 timeout 秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.

代理访问

采集时为避免被封IP,经常会使用代理。requests也有相应的proxies属性。

import requests

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

requests.get("http://www.zhidaow.com", proxies=proxies)

如果代理需要账户和密码,则需这样:

proxies = {
   "http": "http://user:pass@10.10.1.10:3128/",}

重定向与请求历史

默认情况下,除了 HEAD, Requests 会自动处理所有重定向。

可以使用响应对象的 history 方法来追踪重定向。

Response.history 是一个 Response 对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。

例如,Github 将所有的 HTTP 请求重定向到 HTTPS:

>>> r = requests.get('http://github.com')

>>> r.url
'https://github.com/'

>>> r.status_code
200

>>> r.history
[<Response [301]>]

如果你使用的是GET、OPTIONS、POST、PUT、PATCH 或者 DELETE,那么你可以通过 allow_redirects 参数禁用重定向处理:

>>> r = requests.get('http://github.com', allow_redirects=False)
>>> r.status_code
301
>>> r.history
[]

如果你使用了 HEAD,你也可以启用重定向:

>>> r = requests.head('http://github.com', allow_redirects=True)
>>> r.url
'https://github.com/'
>>> r.history
[<Response [301]>]

basic auth 和 oauth

#coding=utf-8

import requests

URL = "https://api.github.com"

def construct_url(end_point):
    return "/".join([URL, end_point])

#basic auth不安全,是将你传入的用户名和密码进行简单的加密并存放在request的headers中进行传递的,可以轻松的将内容进行解码,所以不安全,不建议使用
def basic_auth():
    responce = requests.get(construct_url("user"), auth = ("hetingTester1","952643152HTan"))
    print(responce.request.headers)
    print(responce.text)

#oauth就相对比较安全,什么是oauth认证?比拟第三方授权登录的例子,token的值是第三方的服务方进行提供,调用方根本就不能接触服务方的用户体系。
def basic_oauth():
    #注意,下面的token是我乱写的,在测试的时候需要有实际的token值
    headers = {'authorization':"token kkkjhkfdkfhdjkfhiuyuwehkji"}
    responce = requests.get(construct_url("user/emails"),headers = headers)
    print(responce.text)
    
if __name__ == "__main__":
    basic_auth()
python3 requests出错Traceback (most recent call last):插图
http基本认证
python3 requests出错Traceback (most recent call last):插图(1)
oauth认证

原始响应内容-保存图片,文件到本地

在罕见的情况下,你可能想获取来自服务器的原始套接字响应,那么你可以访问 r.raw。 如果你确实想这么干,那请你确保在初始请求中设置了 stream=True。具体你可以这么做:

>>> r = requests.get('https://github.com/timeline.json', stream=True)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'

但一般情况下,你应该以下面的模式将文本流保存到文件:

with open(filename, 'wb') as fd:
    for chunk in r.iter_content(chunk_size):
        fd.write(chunk)

上面是优先推荐的获取内容方式,还是需要设置stream=True

Cookie

如果某个响应中包含一些 cookie,你可以快速访问它们:

>>> url = 'http://example.com/some/cookie/setting/url'
>>> r = requests.get(url)

>>> r.cookies['example_cookie_name']
'example_cookie_value'

要想发送你的cookies到服务器,可以使用 cookies 参数:

>>> url = 'http://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')

>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{"cookies": {"cookies_are": "working"}}'

Cookie 的返回对象为 RequestsCookieJar,它的行为和字典类似,但界面更为完整,适合跨域名跨路径使用。你还可以把 Cookie Jar 传到 Requests 中:

>>> jar = requests.cookies.RequestsCookieJar()
>>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
>>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
>>> url = 'http://httpbin.org/cookies'
>>> r = requests.get(url, cookies=jar)
>>> r.text
'{"cookies": {"tasty_cookie": "yum"}}'

获取网页编码或设置网页编码

可以使用r.encoding来获取网页编码。

>>> r = requests.get('http://www.zhidaow.com')
>>> r.encoding
'utf-8'

当你发送请求时,requests会根据HTTP头部来猜测网页编码,当你使用r.text时,requests就会使用这个编码。当然你还可以修改requests的编码形式。

>>> r = requests.get('http://www.zhidaow.com')
>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'

像上面的例子,对encoding修改后就直接会用修改后的编码去获取网页内容。

网页状态码

我们可以用r.status_code来检查网页的状态码。

>>>r = requests.get('http://www.mengtiankong.com')
>>>r.status_code
200

>>>r = requests.get('http://www.mengtiankong.com/123123/')
>>>r.status_code
404

>>>r = requests.get('http://www.baidu.com/link?url=QeTRFOS7TuUQRppa0wlTJJr6FfIYI1DJprJukx4Qy0XnsDO_s9baoO8u1wvjxgqN')
>>>r.url
u'http://www.zhidaow.com/
>>>r.status_code
200

前两个例子很正常,能正常打开的返回200,不能正常打开的返回404。但第三个就有点奇怪了,那个是百度搜索结果中的302跳转地址,但状态码显示是200,接下来我用了一招让他原形毕露:

>>>r.history(<Response [302]>,)

这里能看出他是使用了302跳转。也许有人认为这样可以通过判断和正则来获取跳转的状态码了,其实还有个更简单的方法:

>>>r = requests.get('http://www.baidu.com/link?url=QeTRFOS7TuUQRppa0wlTJJr6FfIYI1DJprJukx4Qy0XnsDO_s9baoO8u1wvjxgqN', 
allow_redirects = False)
>>>r.status_code
302

只要加上一个参数allow_redirects,禁止了跳转,就直接出现跳转的状态码了,好用吧?

响应头内容

可以通过r.headers来获取响应头内容。

>>>r = requests.get('http://www.zhidaow.com')
>>> r.headers
{
   'content-encoding': 'gzip',
   'transfer-encoding': 'chunked',
   'content-type': 'text/html; charset=utf-8';
   ...}

可以看到是以字典的形式返回了全部内容,我们也可以访问部分内容。

>>> r.headers['Content-Type']
'text/html; charset=utf-8'
>>> r.headers.get('content-type')
'text/html; charset=utf-8'

持久连接keep-alive

requests的keep-alive是基于urllib3,同一会话内的持久连接完全是自动的。同一会话内的所有请求都会自动使用恰当的连接。

也就是说,你无需任何设置,requests会自动实现keep-alive

响应状态码

我们可以检测响应状态码:

>>> r = requests.get('http://httpbin.org/get')
>>> r.status_code
200

为方便引用,Requests还附带了一个内置的状态码查询对象:

>>> r.status_code == requests.codes.ok
True

如果发送了一个错误请求(一个 4XX 客户端错误,或者 5XX 服务器错误响应),我们可以通过 Response.raise_for_status() 来抛出异常:

>>> bad_r = requests.get('http://httpbin.org/status/404')
>>> bad_r.status_code
404

>>> bad_r.raise_for_status()
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error

但是,由于我们的例子中 r 的 status_code 是 200 ,当我们调用 raise_for_status() 时,得到的是:

>>> r.raise_for_status()
None

一切都挺和谐哈。

请求头内容

请求头内容可以用r.request.headers来获取。

>>> r.request.headers
{'Accept-Encoding': 'identity, deflate, compress, gzip','Accept': '*/*', 'User-Agent': 'python-requests/1.2.3 CPython/2.7.3 Windows/XP'}

错误与异常

遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError 异常。

如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status() 会抛出一个 HTTPError 异常。

若请求超时,则抛出一个 Timeout 异常。

若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。

所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException 。

#coding=utf-8

import requests
from requests import exceptions

try:
    responce = requests.get("https://developer.github.com/v3/users/", timeout = 0.01)
except exceptions.Timeout as e:
    print(e)

喃懂妳 » python3 requests出错Traceback (most recent call last):

发表回复

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

查看更多实用工具

立即查看 了解详情