httplib2,一个第三方的开源库,它比http.client更完整的实现了http协议,同时比urllib.request提供了更好的抽象。 api
#coding=utf8 import httplib2 #获取HTTP对象 h =httplib2.Http() #发出同步请求,并获取内容 resp, content = h.request("http://www.weirdbird.net/") print resp print content
一旦你有了Http对象, 获取数据很是简单,以你要的数据的地址做为参数调用request()方法就能够了。这会对该url执行一个http GET请求 缓存
request() 方法返回两个值。第一个是一个httplib2.Response对象,其中包含了服务器返回的全部http头。好比, status为200 表示请求成功。 服务器
content 变量包含了http服务器返回的实际数据。数据以bytes对象返回,不是字符串。 若是你须要一个字符串,你须要肯定字符编码并本身进行转换 网络
#coding=utf8 import httplib2 #获取HTTP对象 h =httplib2.Http('.cache') #发出同步请求,并获取内容 resp, content = h.request("http://www.weirdbird.net/sitemap.xml") print resp # print content print("......"*3) httplib2.debuglevel = 1 h1 = httplib2.Http('.cache') resp,content = h1.request('http://www.weirdbird.net/sitemap.xml') print(resp) print('debug',resp.fromcache)
此时debug 是true ,说明 是从 本地的.cache 进行读取,没通过原网站,若我不读缓存怎么办? head 上加: app
resp,content = h1.request('http://www.weirdbird.net/sitemap.xml',headers={'cache-control':'no-cache' })
httplib2 容许你添加任意的http头部到发出的请求里。为了跳过全部缓存(不单单是你本地的磁盘缓存,也包括任何处于你和远程服务器之间的缓存代理服务器), 在headers字典里面加入no-cache头就能够了。 ide
故名思议, 这个是当服务器的资源改变了,若本地的缓存还有,进行更新的 网站
http 为这种目的定义了Last-Modified和Etag头。 这些头被称为验证器(validators)。若是本地缓存已经不是新鲜的,客户端能够在下一个请求的时候发送验证器来检查数据实际上有没有改变。若是数据没有改变,服务器返回304状态码,但不返回数据。 因此虽然还会在网络上有一个来回,可是你最终能够少下载一点字节。 google
这可能会让人有些困惑。这里实际上有两个 状态码 — 304 (服务器此次返回的, 致使httplib2查看它的缓存), 和 200 (服务器上次返回的, 并和页面数据一块儿保存在httplib2的缓存里)。response.status返回缓存里的那个 编码
每一次httplib2 发送请求,它包含了Accept-Encoding头来告诉服务器它可以处理deflate 或者 gzip压缩。 url
当request()方法返回的时候,httplib2就已经解压缩了响应的体(body)并将其放在 content变量里。若是你想知道响应是否压缩过, 你能够检查response['-content-encoding']; 不然,不用担忧了.
302临时重定向
调用request()方法返回的response是最终url的响应 ttplib2 会将最终的 url以 content-location加入到 response字典中。这不是服务器返回的头,而是httplib2 特色的特征
response.previous属性持有前一个响应对象的引用,httplib2跟随那个响应得到了当前的响应对象。
response 和 response.previous 都是 httplib2.Response 对象。
这意味着你能够经过response.previous.previous 来反向跟踪重定向链到更前的请求。(场景: 一个url 重定向到第二个url,它又重定向到第三个url。这可能发生!) 在这例子里,咱们已经到达了重定向链的开头,全部这个属性是None.
咱们再次请求同一个url 发现变回了第一次 那样的返回
301 永久重定向
一旦 httplib2跟随了一个永久重定向, 全部后续的对这个url的请求会被透明的重写到目标url 而不会接触网络来访问原始的url。 记住, 调试还开着, 但没有任何网络活动的输出。
POST 请求同GET 请求不一样,由于是要提交到服务器的, 这个api方法必须的参数是status, 而且它应该是url编码过的。 这是一种很简单的序列化格式,将一组键值对(好比字典)转化为一个字符串。
POST 构造数据发送
from urllib.parse import urlencode import httplib2 httplib2.debuglevel = 1 h = httplib2.Http('.cache') data = {'status': 'Test update from Python 3'} h.add_credentials('diveintomark', 'MY_SECRET_PASSWORD', 'identi.ca') resp, content = h.request('https://identi.ca/api/statuses/update.xml', 'POST', urlencode(data), headers={'Content-Type': 'application/x-www-form-urlencoded'})
add_credentials()方法的第三个参数是该证书有效的域名。你应该老是指定这个参数! 若是你省略了这个参数,而且以后重用这个httplib2.Http对象访问另外一个须要认证的站点,可能会致使httplib2将一个站点的用户名密码泄漏给其余站点。
记住, httplib2返回的数据老是字节串(bytes), 不是字符串。为了将其转化为字符串,你须要用合适的字符编码进行解码 好比:
print(content.decode('utf-8'))
from xml.etree import ElementTree as etree tree = etree.fromstring(content) status_id = tree.findtext('id') url = 'https://identi.ca/api/statuses/destroy/{0}.xml'.format(status_id) resp, deleted_content = h.request(url, 'DELETE')