Scrapy框架-模拟登录之JWT验证及post特殊格式数据(json)

简介: 一、背景之前有记录过普通的scrapy模拟登录,这种方法可以满足了日常爬虫的登录需求。但是技术一直在进步,近几年前后端分离的趋势越来越好,很多web都采用前后端分离的技术。

一、背景

之前有记录过普通的scrapy模拟登录,这种方法可以满足了日常爬虫的登录需求。

但是技术一直在进步,近几年前后端分离的趋势越来越好,很多web都采用前后端分离的技术。那么登录后的用户权限验证就会出现jwt的形式。(主要是token方式的验证,在模拟登录中要解决的问题)

这里记录一下。

二、登录操作

前后端分离的项目,一般都是react、vue等js语言编写的(没有这方面经验的同志,可以不用往下看了)

有些会采用成型的前端框架,如AntDesign,ElementUI等,它们写出来的web页面,如果用css定位或者xpath定位,是很不准确的。所以最好的办法就是观察数据流,找到api和发送的参数进行构造。

输入图片说明

以这里的登录为例,通过css定位其实也可以,但是有不稳定的风险。所以还是看api和参数比较稳妥,毕竟css怎么变,api都不会随意改变。

输入图片说明

选中post那条数据流,看到右侧的请求地址、请求头和参数

输入图片说明

[图片上传失败...(image-9401fa-1531469273677)]

这样就可以根据请求地址、请求头和参数来构造登录用的代码:

    def start_requests(self):
        """ 重载start_requests方法 通过is_login方法判断是否成功登录 """
        login_url = "http://xxx.yyy.ccc.aa/api/v1/oauth/login"
        login_data = {
            "username": "abcd@easub.com",
            "password": "faabbccddeeffggd5",
            "type": "email"
        }

        return [scrapy.FormRequest(url=login_url, formdata=login_data, callback=self.is_login)]

    def is_login(self, response):
        """
        根据返回值中的message值来判断是否登录成功
            如果登录成功则对数据传输页发起请求,并将结果回传给parse方法
            如果登录失败则提示
        由于后面的用户权限验证需要用到token信息,所以这里取到登录后返回的token并传递给下一个方法
        """
        results = json.loads(response.text)
        if results['message'] == "succeed":
            urls = 'http://xxx.yyy.ccc.aa'
            access_token = results['data']['access_token']
            print("登录成功,开始调用方法")
            yield Request(url=urls, callback=self.parse, meta={"access_token": access_token})
        else:
            print("登录失败,请重新检查")

如果返回信息的json里面message值为succeed及认为登录成功,并调用parse方法。

三、用户权限验证

登录完毕后,我想执行其他的操作,比如上传(post)数据,跟刚才一样,需要观察api的地址和所需参数请求头信息等。

输入图片说明
输入图片说明

同样是根据返回的参数和请求头,来构造代码

然而这次却不行,返回的状态码是401,由于scrapy默认只管200和300的状态码,4开头和5开头的都不处理。但是又需要观察401状态返回的东西,可以在settings.py中空白处新增代码:

""" 状态码处理 """
HTTPERROR_ALLOWED_CODES = [400, 401]

然后在下一个方法中观察response回来的数据。

======================================

后来又查询了401的意思,就是未获得授权,也就是用户权限验证不通过,经过多方资料查找,发现请求头中有这么一条:

[图片上传失败...(image-1322be-1531469273677)]

它就是用于用户权限验证的,authorization的值分为两部分<type>和<credentials>,前者是验证采用的类型,后者是具体的参数值。这里的类型可以看到用的是Bearer类型,(传说值默认是用户名+密码的base64字符串,但这个这么长,显然不是64)。

我又去观察登录时候的返回值,发现登录成功后的返回值除了succeed之外,还有其他的一些返回值,里面包括了一个叫access_token的字段,它是用于JWT登录方式用来鉴权的token信息,而且authorization用的也正好就是这个token作为值。

那么代码就应该在第一次登录时候,取出access_token的值,并传递下去,用于后面请求的鉴权:

    def is_login(self, response):
        """
        根据返回值中的message值来判断是否登录成功
            如果登录成功则对数据传输页发起请求,并将结果回传给parse方法
            如果登录失败则提示
        由于后面的用户权限验证需要用到token信息,所以这里取到登录后返回的token并传递给下一个方法
        """
        results = json.loads(response.text)
        if results['message'] == "succeed":
            urls = 'http://xxx.yyy.ccc.aa'
            access_token = results['data']['access_token']
            print("登录成功,开始调用方法")
            yield Request(url=urls, callback=self.parse, meta={"access_token": access_token})
        else:
            print("登录失败,请重新检查")

下面的pase方法中,将authorization设定到header中以对数据进行请求:

header = {
            "authorization": "Bearer " + access_token
        }

这样就解决了用户权限的问题,不再出现401

四、postman发送请求特殊格式数据(json)

在parse方法中,根据浏览器观察到的参数,进行构造:

datas = {
                "url": "https://www.youtube.com/watch?v=eWeACm7v01Y",
                "title": "看上去可爱其实很笨的狗#动物萌宠#",
                "share_text": "看上去可爱其实很笨的狗#动物萌宠#[doge]",
                "categories": {'0': '00e2e120-37fd-47a8-a96b-c6fec7eb563d'}
        }

由于categories里面是个数组,所以在构造的时候也可以直接写数据,然后用scrapy.Formdata来进行post。发现返回的状态是这次是400,并且提示:categories必须是数组

再次观察请求头信息,发现请求头信息中还有:

[图片上传失败...(image-e2574e-1531469273677)]

叫做content-type的参数,我将它加入到header中:

        header = {
            "authorization": "Bearer " + access_token,
            "content-type": "application/json",
        }

这样关于categories的提示就没有了。但是返回的状态码依然是400,而且提示变成了url不能为空,这到底又是怎么一回事?

多方探查都没有结果。

真是伤心

后来我又想起了,既然这里的文本类型是application/json,那么提交出去的文本应该是json类型数据,而不是python的dict字典类型数据。

于是打开json在线解析,对传递的参数进行观察,发现这样的数据并不满足json格式:

输入图片说明

后来尝试对它进行更改:

输入图片说明

在外层增加了一对{},然后又将categories的值加上了双引号,才是正确的json格式。

但是如果这样,拿到postman中进行测试,是不行的,后来经过反复测试,最终确定了postman的请求格式为:

输入图片说明
输入图片说明
输入图片说明

对Auth、Headers和Raw进行设置,才终于成功发送post,返回正确的信息!!!

五、scrapy发送Json格式数据

在postman测试通过后,说明这样的做法是可行的,但是代码上怎么编写呢?

用之前的scrapy.Formdata是不行的,它的formdat=默认使用dict格式,如果强行转成json格式也是会报错的。经过群里咨询和搜索,发现要用scrapy.http的Requst方法(平时常用的这个):

access_token = response.meta['access_token']
        urls = "http://aaa.bbb.xxx.yy/api/v1/material/extract"
        datas = {
                "url": "https://www.youtube.com/watch?v=eWeACm7v01Y",
                "title": "看上去可爱其实很笨的狗#动物萌宠#",
                "share_text": "看上去可爱其实很笨的狗#动物萌宠#[doge]",
                "categories": {'0': '00e2e120-37fd-47a8-a96b-c6fec7eb563d'}
        }
        header = {
            "authorization": "Bearer " + access_token,
            "content-type": "application/json",
        }
        yield Request(url=urls, method='POST', body=json.dumps(datas), headers=header, callback=self.parse_details)

这样才发送请求,终于成功了!!!

目录
相关文章
|
29天前
|
JSON 安全 算法
|
29天前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
14天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
18天前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。
|
12天前
|
JSON API 数据安全/隐私保护
拍立淘按图搜索API接口返回数据的JSON格式示例
拍立淘按图搜索API接口允许用户通过上传图片来搜索相似的商品,该接口返回的通常是一个JSON格式的响应,其中包含了与上传图片相似的商品信息。以下是一个基于淘宝平台的拍立淘按图搜索API接口返回数据的JSON格式示例,同时提供对其关键字段的解释
|
2月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
47 1
|
1月前
|
JSON JavaScript Java
在Java中处理JSON数据:Jackson与Gson库比较
本文介绍了JSON数据交换格式及其在Java中的应用,重点探讨了两个强大的JSON处理库——Jackson和Gson。文章详细讲解了Jackson库的核心功能,包括数据绑定、流式API和树模型,并通过示例演示了如何使用Jackson进行JSON解析和生成。最后,作者分享了一些实用的代码片段和使用技巧,帮助读者更好地理解和应用这些工具。
在Java中处理JSON数据:Jackson与Gson库比较
|
1月前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
1月前
|
JSON 前端开发 Java
【Spring】“请求“ 之传递 JSON 数据
【Spring】“请求“ 之传递 JSON 数据
87 2
|
2月前
|
存储 JSON Go
在Gin框架中优雅地处理HTTP请求体中的JSON数据
在Gin框架中优雅地处理HTTP请求体中的JSON数据