python2爬虫之 requests

1.简介

requests第三方封装的模块,通过简化和响应数据的处理,简化繁琐的开发步骤和处理逻辑、统一不同请求的编码风格以及高效的数据处理特性等而风靡于爬虫市场

参考官方文档

Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加 Pythoner。更重要的一点是它支持 Python3 哦!
Beautiful is better than ugly.(美丽优于丑陋)
Explicit is better than implicit.(清楚优于含糊)
Simple is better than complex.(简单优于复杂)
Complex is better than complicated.(复杂优于繁琐)
Readability counts.(重要的是可读性)

2.下载安装

Python2、python3命令行安装

使用pip(python install package)命令安装
pip install requests
or
使用ease_install 命令安装
ease_install requests

3.程序中的使用

原始使用urllib2 请求得到数据程序

#-*- coding:utf-8 -*-

#原始的方式,引入需要的模块
import urllib2

#定义一个请求地址
url="http://www.sojson.com/open/api/weather/json.shtml?city=%E9%83%91%E5%B7%9E"

#创建 一个请求对象
req = urllib2.Request(url)

#向服务器发送请求,得到响应对象
response = urllib2.urlopen(req)
#得到请求数据
pg = response.read()

with open("tq.json","w") as f:
    f.write(pg)

结果展示:
{
"message": "Success !",
"status": 200,
"city": "郑州",
"count": 4,
"data": {
"shidu": "85%",
"pm25": 42.0,
"pm10": 92.0,
"quality": "良",
"wendu": "30",
"ganmao": "极少数敏感人群应减少户外活动",
"yesterday": {
"date": "10日星期四",
"sunrise": "05:41",
"high": "高温 37.0℃",
"low": "低温 25.0℃",
"sunset": "19:20",
"aqi": 141.0,
"fx": "西风",
"fl": "<3级",
"type": "晴",
"notice": "lovely sunshine,尽情享受阳光的温暖吧"
},
"forecast": [
{
"date": "11日星期五",
"sunrise": "05:42",
"high": "高温 36.0℃",
"low": "低温 25.0℃",
"sunset": "19:19",
"aqi": 90.0,
"fx": "南风",
"fl": "<3级",
"type": "晴",
"notice": "晴空万里,去沐浴阳光吧"
},
{
"date": "12日星期六",
"sunrise": "05:42",
"high": "高温 32.0℃",
"low": "低温 23.0℃",
"sunset": "19:18",
"aqi": 61.0,
"fx": "东风",
"fl": "3-4级",
"type": "阵雨",
"notice": "突如其来的雨,总叫让人措手不及"

使用requests模块进行基本的请求响应

#引入requests模块
import requests
#发送请求,得到服务器返回的响应对象,通过encoding设置响应中数据的编码
url = "http://www.sojson.com/open/api/weather/json.shtml?city=%E9%83%91%E5%B7%9E"

response = requests.get(url)
# response.encoding = "utf-8"
#通过text打印响应中的文本数据
print response.text

展示结果:
D:\python_men\pythonScrip\python2\python.exe F:/untitled/rquests方法/demo1.py
{"message":"Success !","status":200,"city":"郑州","count":5,"data":{"shidu":"85%","pm25":42.0,"pm10":92.0,"quality":"良","wendu":"30","ganmao":"极少数敏感人群应减少户外活动","yesterday":{"date":"10日星期四","sunrise":"05:41","high":"高温 37.0℃","low":"低温 25.0℃","sunset":"19:20","aqi":141.0,"fx":"西风","fl":"<3级","type":"晴","notice":"lovely sunshine,尽情享受阳光的温暖吧"},"forecast":[{"date":"11日星期五","sunrise":"05:42","high":"高温 36.0℃","low":"低温 25.0℃","sunset":"19:19","aqi":90.0,"fx":"南风","fl":"<3级","type":"晴","notice":"晴空万里,去沐浴阳光吧"},{"date":"12日星期六","sunrise":"05:42","high":"高温 32.0℃","low":"低温 23.0℃","sunset":"19:18","aqi":61.0,"fx":"东风","fl":"3-4级","type":"阵雨","notice":"突如其来的雨,总叫让人措手不及"},{"date":"13日星期日","sunrise":"05:43","high":"高温 31.0℃","low":"低温 24.0℃","sunset":"19:17","aqi":58.0,"fx":"东风","fl":"<3级","type":"多云","notice":"今日多云,骑上单车去看看世界吧"},{"date":"14日星期一","sunrise":"05:44","high":"高温 32.0℃","low":"低温 23.0℃","sunset":"19:16","aqi":62.0,"fx":"东风","fl":"<3级","type":"晴","notice":"晴空万里,去沐浴阳光吧"},{"date":"15日星期二","sunrise":"05:45","high":"高温 33.0℃","low":"低温 24.0℃","sunset":"19:14","aqi":67.0,"fx":"东风","fl":"<3级","type":"晴","notice":"晴空万里,去沐浴阳光吧"}]}}
Process finished with exit code 0

4.基本请求方式

常规情况下,所有类似的服务器发送的请求方式,都是参考w3c提供的标准进行制定的。

requests为爬虫开发者们提供了8中基本请求方式,分别如下

req = requests.request(method,url,**kw)
req = requests.post(url,**kw)
req = requests.get(url,**kw)
req = requests.delete(url,**kw)
req = requests.put(url,**kw)
req = requests.head(url,**kw)
req = requests.options(url,**kw)
req = requests.patch(url,**kw)

注意:由于在web开发过程中,大家发现对于服务器数据的处理方式没有一开始的制定标准时设计的那么复杂,所以一般情况下都简化成了get/post两种常见的请求方式

以上请求方式中,requests()方式是底层的请求方式,分别有get()/post()等方式进行了高级的实现,方便开发人员去更加快捷的使用了

5.基本请求方式

基本请求方式,通过request直接调用对应的函数/方法即可完成

附带参数的get请求方式
# --*-- coding:utf-8 --*--

#get 附带参数的方式
import requests
url = "http://www.sojson.com/open/api/weather/json.shtml"
#可变参数
data = {
    "city":"平顶山"
}
#get 方式请求,包含参数
response = requests.get(url,params=data)

print response.text

附带参数的post请求方式
#post 附带参数得方式
import requests
url = "http://www.sojson.com/open/api/weather/json.shtml"

data = {
    "city":"新乡"
}
# post 方式发送请求,包含参数
response = requests.post(url,data=data)
print (response.text)

5.2传递JSON参数

在请求得过程中,有些URL借口需要的参数并不是零散的数据,而是需要封装在一起的JSON数据,此时,可以通过json.dumps()函数将一个字典数据转换成json数据进行传递

此时,requests符合人体工程学的操作就出现了,如果你提供的是字典数据,json模块提供了dumps()函数转换下就ok了

# --*-- coding:utf-8 --*--

import requests
import json
#附带的参数,要求是JSON格式的数据
#JSON对象{"key":"value"} -- JSON字符串:‘{"key":"value"}’
#通过json.dumps进行json字符串的转换
url = "http://www.sojson.com/open/api/weather/json.shtml"
#封装参数的字典
data = {
    "city":"新乡"
}
#get请求发送,包含转换参数
response = requests.get(url,params=json.dumps(data))
#post请求发送,包含转换参数
# response = requests.post(url,data=json.dumps(data))

print (response.text)

当然,如果提供JSON字符串的话,就容易了

import requests
#封装参数的json字符串
json_data = {"city":"郑州"}
#post方式发送请求,包含参数
res = requests.post("http://..../json.shtml",json = json_data)

5.3返回数据和它的编码操作

返回的数据,可以根据数据的编码类型区分为二进制数据和文本数据,两种不同的数据通过两个不同的属性进行获取
response.content:获取响应中半酣的而二进制数据response.text:获取响应中包含的文本数据
返回的数据,会根据响应的数据进行自动的编码,数据编码最常见的会是ISO-8859-1也就是西欧编码,容易看到乱码的情况,此时可以通过返回的响应对象response的一个属性encoding进行编码的获取和指定
response.encoding = "编码"

'''
#基本请求得方式,获取服务器返回的数据
import requests
#response 响应对象,可以通过encoding属性来获取编码和设置编码【响应对象】
#response 响应对象中包含的数据  文本文件text属性  二进制文件content属性

response = requests.get("http://www.sojson.com/open/api/weather/json.shtml?city=%E9%83%91%E5%B7%9E")
response.encoding = "ISO-8859-1"
print (response.encoding)
print (response.text)
print (response.content)

'''
'''
#通过响应对象的数据和数据编码的指定,来操作响应对象中包含的数据
import requests
url = "http://www.kanunu8.com/book3/8439/187638.html"
response = requests.get(url)
response.encoding = "GBK"
print (response.text)
'''

5.4定制header

# -*- coding:utf-8 -*-
# 目标服务器->爬虫->请求头[header:对请求对象的描述信息,间接描述客户端信息]

import requests

header = {
    "User-agent":"Mozila5.0/...."
}
response = requests.get("http://www.sojson.com/open/api/weather/json.shtml\
?city=%E9%83%91%E5%B7%9E",headers=header)

print response.text
import requests
import json
 
data = {'some': 'data'}
headers = {'content-type': 'application/json',
           'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
 
r = requests.post('https://api.github.com/some/endpoint', data=data, headers=headers)
print(r.text)

5.5 Response对象

使用requests方法后,会返回一个requests对象,其存储了服务器相应的内容,如上事例中已经提到的r.text
获取文本方式的响应体实例:当你访问r.text之时,会使其相应的文本编码进行解码,并且你可以修改其编码让r.text使用自定义的编码进行解码。

r = requests.get('http://www.itwhy.org')
print(r.text, '\n{}\n'.format('*'*79), r.encoding)
r.encoding = 'GBK'
print(r.text, '\n{}\n'.format('*'*79), r.encoding)

其他响应:

r.status_code #响应状态码
r.raw #返回原始响应体,也就是 urllib 的 response 对象,使用 r.raw.read() 读取
r.content #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩
r.text #字符串方式的响应体,会自动根据响应头部的字符编码进行解码
r.headers #以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
特殊方法
r.json() #Requests中内置的JSON解码器
r.raise_for_status() #失败请求(非200响应)抛出异常
案例:

import requests
 
URL = 'http://ip.taobao.com/service/getIpInfo.php'  # 淘宝IP地址库API
try:
    r = requests.get(URL, params={'ip': '8.8.8.8'}, timeout=1)
    r.raise_for_status()    # 如果响应状态码不是 200,就主动抛出异常
except requests.RequestException as e:
    print(e)
else:
    result = r.json()
    print(type(result), result, sep='\n')

5.6 文件上传

#文件传输
import requests

#传统的文件上传方式,首先将整个文件,加载到内存中,然后再上传
f = open("D:/test.txt","r")

file = {"file":f}

headers = {
    "User-agent":"Mozila-damu"
}
response = requests.post("http://httpbin.org/post",files=file,headers=headers)
print response.text
f.close()

文件流式上传

import requests
#文件流式上传
with open("d:/test.txt","r") as f:
    response = requests.post("http://httpbin.org/post",data=f)
print (response.text)

6 身份验证

基本身份认证(HTTP Basic Auth)

import requests
from requests.auth import HTTPBasicAuth
 
r = requests.get('https://httpbin.org/hidden-basic-auth/user/passwd', auth=HTTPBasicAuth('user', 'passwd'))
# r = requests.get('https://httpbin.org/hidden-basic-auth/user/passwd', auth=('user', 'passwd'))    # 简写
print(r.json())

另一种非常流行的HTTP身份认证形式是摘要式身份认证,Requests对它的支持也是开箱即可用的

requests.get(URL, auth=HTTPDigestAuth('user', 'pass'))

7.Cookies 与会话对象

cookie 操作是web开发过程中经常用到的一个功能,在爬虫操作过程中也是非常使用的功能,可以用于进行诸如登录状态记录、浏览记录等很多非常实用的功能

在requests模块中对cookie的操作进行了封装,可以直接通过响应对象的cookie属性进行操作

# cookie操作,测试服务器地址:
#设置cookie值:http://httpbin.org/cookies/set/key/value
#获取cookie值:http://httpbin.org/cookies

import requests

#第一次请求,设置cookie值
response = requests.get("http://httpbin.org/cookies/set/name/xiaoqiang")
response.cookies["age"] = 12 #设置cookie信息
print (response.cookies["age"]) #获取cookie信息
print(response.text)

#再次发起请求,获取cookies值
response = requests.get("http://httpbin.org/cookies")
print(response.text)

#设置会话session,让多个请求在一个会话中进行
#是否需要会话跟踪:我们的多次请求是否要保持会话
req_session = requests.Session()

#第一次请求,设置了cookie值
response = req_session.get("http://httpbin.org/cookies/set/name/xiaoqiang")
print (response.text)

#再次发起请求:获取cookies值
response = req_session.get("http://httpbin.org/cookies")
print(response.text)

8.请求超时设置

# -*- coding:utf-8 -*-

#请求超时配置
import requests
#要求制定网址必须在制定的时间范围内访问到
#请求得数据没有在指定的时间内返回~抛出异常~程序出错~处理异常
#当爬取某些数据时,根据数据正常访问的时间设置一个固定的超时配置~用来提高爬虫的数据获取效率

response = requests.get("http://www.github.com", timeout=0.1)
print (response.text)

异常:
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)

所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException:ConnectionError、HTTPError、Timeout、TooManyRedirects。

9.SSL证书设置

SSL 证书设置 ,可以让爬虫程序类似浏览器一样验证 https 协议访问的网站 ,为 https 请 求验证 SSL 证书 。
测试一下 :(某 12306 网站的数字证书可是无效哦 网站的数字证书可是无效哦 网站的数字证书可是无效哦 )如

Paste_Image.png

爬虫程序取该网页会出现什么问题呢 ?

#-*- coding:utf-8 -*-
import requests
response = requests.get("https://kyfw.12306.cn/otn")

print (response.text)

错误:
 raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='kyfw.12306.cn', port=443): Max retries exceeded with url: /otn (Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)'),))

此时 ,关闭掉爬虫对HTTPS的SSL证书验证,通过设置请求参数verify=False关闭该验证

#-*- coding:utf-8 -*-
import requests
response = requests.get("https://kyfw.12306.cn/otn",verify=False)

print (response.text)

返回正确信息:


Paste_Image.png

10.代理设置

和之前的urllib2一样,爬虫操作过程中,代理的设置是不可避免的一种技术手段,在requests模块中,当然也是考虑了而代理操作的可行性
通过将代理服务器端口配置在字典中,然后通过Proxies参数进行设置即可

import requests
proxies = {
    "http":"115.215.50.245:8118"
}

response = requests.get("https://kyfw.12306.cn/otn",
                        verify=False, proxies=proxies)
print (response.text)




#当访问某些地址的时候需要账号密码验证:ftp服务器
import requests
response = requests.get("ftp://192.168.10.25", auth=("test", "123123"))
print (response.text)


本文参考:
python-第三方库requests详解
简书:大牧莫邪

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容