爬虫-requests学习

requests概述

requests官方slogan是这样一句话:

Requests is the only Non-GMO HTTP library for Python, safe for human consumption.

针对谁不言而喻,urllib和urllib2的槽点太多,这不必说。问题是requests是否有吐槽他们的资格呢,它到底有多便利?

Requests 完全满足今日 web 的需求:

  • Keep-Alive & 连接池
  • 国际化域名和 URL
  • 带持久 Cookie 的会话
  • 浏览器式的 SSL 认证
  • 自动内容解码
  • 基本/摘要式的身份认证
  • 优雅的 key/value Cookie
  • 自动解压
  • Unicode 响应体
  • HTTP(S) 代理支持
  • 文件分块上传
  • 流下载
  • 连接超时
  • 分块请求
  • 支持 .netrc

requests安装

requests库并非出自python基金会,一般安装python后不会自带requests,使用时需要安装:

pip install requests

requests类和方法

requests发展至今,功能上有很大扩展,类和方法也是很多。这里主要将一些爬虫常用的,希望兼顾实用和全面。

requests.Response类

requests的响应类。

属性 说明
encoding requests从响应的header自动猜测出响应页面编码方式
apparent_encoding requests从响应页面猜测响应页面编码方式
url 响应的url
status_code 响应的http状态码
cookies 响应的cookies
elapsed 发送请求到收到响应消耗的时间
headers 响应的headers
history 请求历史
headers 响应的headers
content 页面源码,str
text 也是页面源码,unicode,requests自动解码

这里需要注意的是,不少人使用requests都有乱码的困扰,就是因为上面属性content和text没搞清楚的问题,以后单独讲讲这个问题。

requests.Session类

提供cookie持久性、连接池和配置。
requests提供的一个会话类,可以使用在爬虫抓取时需要保持登录状态的情况

七个请求方法

如下六个请求方法:

  • requests.get(url, params=None, **kwargs)
  • requests.post(url, data=None, json=None, **kwargs)
  • requests.head(url, **kwargs)
  • requests.put(url, data=None, **kwargs)
  • requests.patch(url, data=None, **kwargs)
  • requests.delete(url, **kwargs)
    还有一个:
  • requests.request(method, url, **kwargs)

以上就是requests全部的访问方法,并且全部都返回Request对象。
有点被吓到了,那么我们仅仅使用

requests.get(url, params=None, **kwargs)
requests.post(url, data=None, json=None, **kwargs)

这两个即可,分别是get请求和post请求,其他的在爬虫中使用率不高。

请求参数**kwargs

参数 说明
params 自动构建url,get请求时使用
data 提交表单,post请求时使用
headers 请求headers
cookies 请求cookies
timeout 超时时间
proxies ip代理
json 发送json
file 发送文件(Multipart-Encoded)
allow_redirects
auth
verify
stream
cert

requests实例讲解

get方法-基本

这里我们看requests发送get方法的例子,并打印requests.Response的各个属性看看

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def first():
    #基本get方法,认识request对象
    url = "http://www.tenliu.top/index.php/httpclient/"
    resp = requests.get(url)
    print resp.url
    print resp.encoding
    print resp.apparent_encoding
    print resp.headers
    print resp.cookies
    print resp.elapsed
    print resp.status_code
    print resp.ok
    print resp.reason
    print resp.history
    print resp.text
    print resp.content
if __name__=="__main__":
    first()

尴尬了,页面


的encoding是0:00:01.111877,这么慢。

get请求-自动构建url请求参数

requests.get()的params参数,我们上面也说了,可以自动把params参数拼接在url中。当然你也可以手工构建URL。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def second():
    url = "http://www.tenliu.top/index.php/httpclient/"
    payload = {'country': '中国', 'ranking': 2}
    resp = requests.get(url,params=payload)
    print resp.text
if __name__=="__main__":
    second()

执行,打印页面源码,我们看到get请求参数传递成功。

var res = {"headers":{"HTTP_CONNECTION":"keep-alive","HTTP_ACCEPT_ENCODING":"gzip, deflate","HTTP_ACCEPT":"\/","HTTP_USER_AGENT":"python-requests\/2.11.1","REQUEST_METHOD":"GET"}, "params":{"country":"\u4e2d\u56fd","ranking":"2"}};

同时,这里我们注意到requests再也不用urlencode编码啦。urllib和urllib2惭不惭愧。
爬虫-urllib2学习

post方法

requests.post()中data用来post参数

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def thrid():
    url = "http://www.tenliu.top/index.php/httpclient/"
    data = {'country': '中国', 'ranking': 2}
    resp = requests.post(url,data=data)
    print resp.text
if __name__=="__main__":
    thrid()

执行打印页面源码,可以看到post方式传递参数成功:

var res = {"headers":{"HTTP_CONNECTION":"keep-alive","HTTP_ACCEPT_ENCODING":"gzip, deflate","HTTP_ACCEPT":"\/","HTTP_USER_AGENT":"python-requests\/2.11.1","REQUEST_METHOD":"POST"}, "params":{"country":"\u4e2d\u56fd","ranking":"2"}};

伪装headers

以上的爬虫都是没有伪装的,看看之前例子的执行结果中:
"HTTP_USER_AGENT":"python-requests\/2.18.4"

USER_AGENT是python-requests/2.18.4(我安装的是2.18.4版本),明确告诉服务器自己爬虫的身份了,被ban也是活该啦。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def fourth():
    url = "http://www.tenliu.top/index.php/httpclient/"
    data = {'country': '中国', 'ranking': 2}
    headers = {
        'Cookie':'sugstore=1; type=test',
        'User-Agent':'Mozilla/5.0  test',
    }
    resp = requests.post(url,data=data,headers=headers)
    print resp.text 
if __name__=="__main__":
    fourth()

执行打印源码,可以看到伪装成功。

var res = {"headers":{"HTTP_CONNECTION":"keep-alive","HTTP_ACCEPT_ENCODING":"gzip, deflate","HTTP_ACCEPT":"\/","HTTP_USER_AGENT":"Mozilla\/5.0 test","HTTP_COOKIE":"sugstore=1; type=test","REQUEST_METHOD":"POST"},"params":{"country":"\u4e2d\u56fd","ranking":"2"}};

ip代理

这里我们使用ip代理抓取页面:
http://tool.chinaz.com/

至于为什么不抓取http://www.tenliu.top/index.php/httpclient/
这个页面是chunked编码传输内容,添加ip代理抓取处理比较麻烦,不是这里要讲的内容)

我自己构建了一个ip代理池,定时验证。这里有一个ip代理的展示页面。可以从这里获取ip代理

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
from lxml import etree
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def fifth():
    url = 'http://tool.chinaz.com/'
    proxy = "121.196.226.246:84"
    proxies = {
        "http": "http://"+proxy,
        "https": "http://"+proxy,
    }
    resp = requests.get(url,proxies=proxies,timeout=32)
    print etree.HTML(resp.text).xpath('//div[@class="Mnav-left fl"]')[0].xpath('string(.)')
if __name__=="__main__":
    fifth()

执行结果如下

IP查询 - 您的 IP:121.196.226.246 来自:浙江省杭州市 阿里巴巴网络有限公司

上面例子中有

from lxml import etree

print etree.HTML(resp.text).xpath('//div[@class="Mnav-left fl"]')[0].xpath('string(.)')

这里涉及到页面提取的xpath语法,和python对xpath的支持包lxml,也不是这里讲的内容,下一篇会单独说说“页面解析”,这也是爬虫很重要的内容。

session

下面是session的简单例子,更详细的用法还要在实际应用中施展。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
from lxml import etree
import sys
reload(sys) 
sys.setdefaultencoding('utf8')
def sixth():
    #session
    url = "http://www.tenliu.top/index.php/httpclient/"
    s = requests.Session()
    resp = s.get(url)
    print resp.text
if __name__=="__main__":
    sixth()

这个例子当然很简单,更具体的使用场景是:
在抓取需要登录信息的页面时,如果没有session,只能保存cookies,在每次抓取时都发送cookies。但是使用session,登录后可以不用考虑cookies了。

先到这里吧,以后再说页面提取。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: