tenliu的爬虫-requests学习
- 基本爬虫知识python库urllib、urllib2、requests
- urllib、urllib2、request三者关系
- 从python的urllib开始
- urllib2学习
- requests学习
- ps:如何用浏览器抓包分析
- ps:爬虫分析小工具
- 页面提取
- 正则表达式
- xpath
- beautifulsoup
- 动态页面抓取selenium+phantomjs
- scrapy框架
- 基本用法
- 中间件-代理、登录
- 抓取环
- 分布式爬虫
- scrapy_redis,
- scrapy-cluster(加入kafka利器)
- scrapy的改造
- 自定义下载器
- 手机app数据抓取
- 利用代理抓接口(青花瓷)
- appium(selenium和appium原本都是自动化测试工具,用来做爬虫也是很好的)
通过以上学习,爬虫算是入门了,掌握urllib、urllib2我们已经具备了可以抓取网上大部分页面的能力了。
但是我们前面也已经讲了urllib和urllib2的槽点,可以用来做爬虫,但是比较不便,有点违背python的主旨了。
这里介绍 python的第三方库: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()
尴尬了,页面
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了。
先到这里吧,以后再说页面提取。