(二)Requests

Requests概述:让 HTTP 服务人类

Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。

Requests库的优势

Requests 允许你发送纯天然,植物饲养的 HTTP/1.1 请求,无需手工劳动。你不需要手动为 URL 添加查询字串,也不需要对 POST 数据进行表单编码。Keep-alive 和 HTTP 连接池的功能是 100% 自动化的,一切动力都来自于根植在 Requests 内部的 urllib3

为什么使用Requests库

  • requests在python2 和python3中通用,方法完全一样,urllib2在python2和python3中的名称不同
  • 工作中爬虫基本都使用requests
  • 虽然Python的标准库中 urllib 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 "HTTP for Humans",说明使用更简洁方便。requests 继承了urllib的所有特性,requests的底层实现就是urllib2。
  • requests能够自动帮助我们解压(gzip压缩的等)网页内容,简单易用
  • Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。
  • Requests库使用非常广泛,Twitter、Spotify、Microsoft、Amazon、Lyft、BuzzFeed、Reddit、NSA、女王殿下的政府、Amazon、Google、Twilio、Mozilla、Heroku、PayPal、NPR、Obama for America、Transifex、Native Instruments、Washington Post、Twitter、SoundCloud、Kippt、Readability、以及若干不愿公开身份的联邦政府机构都在内部使用。


Warning:非专业使用其他 HTTP 库会导致危险的副作用,包括:安全缺陷症、冗余代码症、重新发明轮子症、啃文档症、抑郁、头疼、甚至死亡:)。

功能特性

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

  • Keep-Alive & 连接池
  • 国际化域名和 URL
  • 带持久 Cookie 的会话
  • 浏览器式的 SSL 认证
  • 自动内容解码
  • 基本/摘要式的身份认证
  • 优雅的 key/value Cookie
  • 自动解压
  • Unicode 响应体
  • HTTP(S) 代理支持
  • 文件分块上传
  • 流下载
  • 连接超时
  • 分块请求
  • 支持 .netrc
  • Requests 支持 Python 2.6—2.7以及3.3—3.7,而且能在 PyPy 下完美运行。

开源地址:https://github.com/kennethreitz/requests
中文文档 API: http://docs.python-requests.org/zh_CN/latest/index.html

安装requests

$ pip install requests

基本GET请求(headers参数 和 parmas参数)

最基本的GET请求可以直接用get方法

import requests
resp = requests.get('http://www.neuedu.com')
print(resp)
# <Response [200]>
# 也可以这么写
response = requests.request("get", "http://www.neuedu.com")
print(response)
# <Response [200]>

response.text 和response.content的区别

import requests
url = 'http://www.baidu.com/'
r = requests.get(url)
# 查看响应内容 str类型
#r.text
r.encoding
'ISO-8859-1'
# 手动修改相应编码格式
r.encoding = 'utf-8'
r.encoding
'utf-8'
# 直接把相应数据改成utf-8
# r.content.decode()
# 获取响应头
r.headers
{'Accept-Ranges': 'bytes', 'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Content-Length': '2381', 'Content-Type': 'text/html', 'Date': 'Mon, 17 Jun 2019 15:13:04 GMT', 'Etag': '"588604c4-94d"', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:32 GMT', 'Pragma': 'no-cache', 'Server': 'ATS/8.0.3', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Age': '0', 'Connection': 'keep-alive'}

添加 headers 和 查询参数

为什么请求需要带上header?
模拟浏览器,欺骗服务器,获取和浏览器一致的内容
headers的形式:字典

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"} 
# 用法: 
requests.get(url,headers=headers)

发送带参数的请求

什么叫做请求参数:
列1: http://www.webkaka.com/tutorial/server/2015/021013/ 不是
例2: https://www.baidu.com/s?wd=python&c=b

import requests

kw = {'wd':'东软'}

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
response = requests.get("http://www.baidu.com/s?", params=kw, headers = headers)

# 查看响应内容,response.text 返回的是Unicode格式的数据
print(response.text)


# 查看响应内容,response.content返回的字节流数据
print(response.content)

# 查看完整url地址
print(response.url)

# 查看响应头部字符编码
print(response.encoding)

# 查看响应码
print(response.status_code)

没有添加请求头的知乎网站

import requests
url = 'https://www.zhihu.com'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

r = requests.get(url)
r.status_code 
400
r = requests.get(url,headers= headers)
r.status_code
200

案例:百度贴吧的爬取

  • 获取指定页数
  • 将贴吧保存成文件
    参考代码:
import requests


"""
目标:
爬取百度贴吧页面:
1、构造url
2、构造请求头
3、发送请求
4、保存数据

"""
class Baidu(object):

    def __init__(self,name,pn):
        # 保存传入的贴吧名称
        self.name = name
        self.url = 'https://tieba.baidu.com/f?kw={}&ie=utf-8&pn='.format(name)
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
        }
        # 构造url列表,拼接的页数
        self.url_list = [self.url + str(pn*50) for pn in range(pn)]
        print(self.url_list)


    # 发送请求获取数据,需要修改传入的url
    def get_data(self,url):
        response = requests.get(url,headers=self.headers)
        return response.content

    # 保存数据
    def save_data(self,data,num):
        # 构造保存数据的文件名称
        file_name = self.name + '_' + str(num) + '.html'
        with open(file_name,'wb') as f:
            f.write(data)

    # 执行方法
    def run(self):
        # 遍历url列表
        for url in self.url_list:
            # print (url)
            # 调用发送请求的方法,获取数据
            data = self.get_data(url)
             # 获取self.url_list索引值
            num = self.url_list.index(url)
            # 调用保存数据的方法
            self.save_data(data,num)
import sys

if __name__ == '__main__':
    # 传入参数,贴吧名称,页数
    name = sys.argv[1]
    pn = int(sys.argv[2])
    # print(type(name))
    # print(type(pn))
    # print(name,pn)
    baidu = Baidu(name,pn)
    baidu.run()

在终端运行如下命令:

python3 spider_tieba.py 李毅 3

本地会生成3个html文件哦


Requests高阶(POST)

发送POST请求

哪些地方我们会用到POST请求:

  • 登录注册( POST 比 GET 更安全)绝大多数的登录会使用post请求,极少数网站仍然在使用get请求进行登录

  • 向服务器传输的数据量比较多的时候,或者向服务器传输大文件

  • 所以同样的,我们的爬虫也需要在这两个地方回去模拟浏览器发送post请求

用法:

response = requests.post(url, data = data, headers=headers)
# data 的形式:字典

案例:访问金山词霸在线翻译,获取翻译结果

网址:http://fy.iciba.com/
需求
1、构造url
2、请求头
3、构造请求体
4、发送请求,输出数据
如下如是浏览器的演示效果,接下来我们要用python代买去实现这一功能


注释:

  • 1.XHR:筛选使用Ajax请求的network(ajax技术的核心是XMLHttpRequest对象(简称XHR),这是由微软首先引入的一个特性,其他浏览器提供商后来都提供了相同的实现。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以异步方式从服务器取得更多信息,意味着用户单击后,可以不必刷新页面也能取得新数据)

  • 2.当左侧输入框发生 变化就会触发Ajax请求事件

    1. Form Data就是post请求的表单数据
      参考代码:
import requests
import json

class JinShan(object):

    def __init__(self,word):
        self.url = 'http://fy.iciba.com/ajax.php?a=fy'
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
        }
        # 构造请求的参数
        self.post_data = {
            "f": "auto",
            "t": "auto",
            "w": word
        }
    # 发送请求
    def request_post(self):
        response = requests.post(url=self.url,headers=self.headers,data=self.post_data)
        # print(response.content.decode())
        return response.content.decode()

    # 解析数据
    def parse_data(self,data):
        # 把响应数据转成字典
        dict_data = json.loads(data)
        # 判断out键是否存在,不能判断一个字符串是否在字典的索引
        # if 'out' in data:
        #     content = (dict_data['content']['out'])
        # else:
        #     content = (dict_data['content']['word_mean'][0])
        # 进行异常处理
        try:
            content = (dict_data['content']['out'])
        except:
            content = (dict_data['content']['word_mean'][0])
        print (content)

    def run(self):
        # 调用发送请求,并获取数据
        data = self.request_post()
        # 调用解析数据方法
        self.parse_data(data)

if __name__ == '__main__':
    import sys
    word = sys.argv[1]
    jinshan = JinShan(word)
    jinshan.run()

在终端运行命令之后会有下面的效果


使用IP代理爬虫

IP代理既代理服务器,其功能主要就是代理网络用户去获取网络信息,形象的说就是网络信息的中转站
为什么爬虫需要使用代理?

  • 让目标服务器以为不是同一个客户端在请求,放置因为ip发送请求过多而被反爬
  • 防止我们的真实地址被泄露,防止被追究


代理分类


使用免费代理网站,比如快代理https://www.kuaidaili.com/free/找到免费的ip

下面是使用代理的示例代码:

import requests


# 使用代理
url = 'http://www.baidu.com/'

# 免费代理
proxies = {
    'http':'http://115.210.24.183:9000',
    'https':'https://183.129.207.86:14002'
}
# # 付费代理,用户名:密码@ip和port
# proxies = {
#     'http':'http://user:pwd@115.223.200.85:9000'
# }


response = requests.get(url,proxies=proxies)
print(response.text)

cookie和session

本质上都是基于键值对的字符串

两者区别:

  • cookie数据存放在客户的浏览器上,session数据放在服务器上
  • cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗(使用用户的cookies获取相关信息
  • session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

利弊:

  • 带上cookie、session的好处:很多网站必须登录之后(或者获取某种权限之后)才能能够请求到相关数据
  • 带上cookie、session的弊端:一套cookie和session往往和一个用户对应.请求太快,请求次数太多,容易被服务器识别为爬虫。从而是账号收到损害
  • 使用建议
    1.不需要cookie的时候尽量不去使用cookie
    2.为了获取登录之后的页面,我们必须发送带有cookies的请求,此时为了确保账号安全应该尽量降低数据采集速度

案例:使用cookies来获取登录之后人人网的响应

首先浏览器登录人人网,然后打开调试模式,复制url和cookie



参考代码如下:

import requests
import re
"""
使用cookie进行模拟登录
1、首先使用浏览器登录网站
2、获取cookie信息
3、保存cookie信息放到请求头中

"""
# 登录后用户信息页
url = 'http://www.renren.com/971209342'

# 保存cookie信息
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
    "Cookie": "anonymid=jx19bd0l-4r5q5y; JSESSIONID=abcsD77Gb0el7fJktQOTw; depovince=GW; _r01_=1; ick_login=19787144-5838-490f-b599-34a22b58aa7c; t=06700184d453813c5b594f40b29cd9412; societyguester=06700184d453813c5b594f40b29cd9412; id=971209342; xnsid=974c659d; jebecookies=7b441396-b2be-4c75-ac03-4466a9fc763f|||||; ver=7.0; loginfrom=null"
}


# 发送请
response = requests.get(url, headers=headers)

# 获取响应,并且解码成str,使用正则获取响应中的字符串
print(re.findall('关注内容', response.content.decode()))
print(response.status_code)



输出结果如下:

['关注内容']
200

Cookies 和 session

如果一个响应中包含了cookie,那么我们可以利用 cookies参数拿到

import requests

url = 'http://www.baidu.com'
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
}

# 设置请求的超时时间,单位是s
# response = requests.get(url,timeout=3)

response = requests.get(url, headers=headers)
# 获取cookie信息
print(response.cookies)

# 把cookie转成字典
content = requests.utils.dict_from_cookiejar(response.cookies)
print(content)
# 将cookie字典转成对象
c = requests.utils.cookiejar_from_dict(content)
print(c)



运行结果:

<RequestsCookieJar[<Cookie H_PS_PSSID=1443_21123_29135_29237_29098_29369_28832_29220_26350 for .baidu.com/>, <Cookie delPer=0 for .baidu.com/>, <Cookie BDSVRTM=0 for www.baidu.com/>, <Cookie BD_HOME=0 for www.baidu.com/>]>
{'H_PS_PSSID': '1443_21123_29135_29237_29098_29369_28832_29220_26350', 'delPer': '0', 'BDSVRTM': '0', 'BD_HOME': '0'}
<RequestsCookieJar[<Cookie BDSVRTM=0 for />, <Cookie BD_HOME=0 for />, <Cookie H_PS_PSSID=1443_21123_29135_29237_29098_29369_28832_29220_26350 for />, <Cookie delPer=0 for />]>

使用session实现人人网登录

在 requests 里,session对象是一个非常常用的对象,这个对象代表一次用户会话:从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开。

会话能让我们在跨请求时候保持某些参数,比如在同一个 Session 实例发出的所有请求之间保持 cookie

import requests
import re

url = 'http://www.renren.com/PLogin.do'

# 保存cookie信息
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
}



# 构造session回话对象
session = requests.session()

# 构造post请求data数据
data = {
    'email':'1900000000',
    'password':'neuedu'
}
# 发送post请求
session.post(url,headers=headers,data=data)

# 验证登录是否成功
response = session.get('http://www.renren.com/963112933')#

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

推荐阅读更多精彩内容