Python爬虫遇到Request-Payload怎么办?

系统 1693 0

前言

最近想用 Python 自动地爬取某个站点里的图片,没想到其请求数据是以 request payload 格式传输给后端进行处理的。博主还是第一次遇到这种情况,写下这篇文章记录一下解决过程。

博主浏览器使用的是 Chrome,下文说的浏览器一律指的是 Chrome浏览器。

POST提交数据常见的几种Content-Type

在网络请求中常用的Content-Type有很多,但是在POST请求下我们常用的Content-Type大约有3种。

1.application/x-www-form-urlencoded

这应该是我们最常见到的POST数据提交方式,原生的表单默认提交方式就是这个,

我用站长工具模拟原生的POST请求,如图1-1:

Python爬虫遇到Request-Payload怎么办?_第1张图片

图1-1

第一个红框可以看到请求的 Content-Type 确实是 application/x-www-form-urlencoded ,第二个红框展示的是向后端请求的数据,它是经过浏览器解码然后展示给我们看的,实际上数据编码格式如图1-2:

图1-2

可以看到,我们请求的数据变成了键值对的形式,并且中间用 & 分隔,形如 key1=val1&key2=val2

2.multipart/form-data

使用表单传数文件时,Content-Type必须是 multipart/form-data ,传输的文件会被分割成多个部分,每部分使用–boundary分割。

大体如图2-1:

图2-1

第二个红框数据也是经过浏览器解码的,原始数据如图2-2:

图2-2

3.application/json

一般情况下,我们遇到的POST请求数据编码格式都是 application/x-www-form-urlencoded ,但是这种格式有局限性,如果想向后端传输复杂的数据,如:

            
              
                {
              
              
                "info"
              
              
                :
              
              
                [
              
              
                {
              
              
                "name"
              
              
                :
              
              
                "Kelvin"
              
              
                ,
              
              
                "age"
              
              
                :
              
              
                18
              
              
                }
              
              
                ]
              
              
                }
              
            
          

这个时候,采用 application/x-www-form-urlencoded 对数据进行编码的话,就不是很方便。

对于像这种复杂的数据,一般都是以json格式直接传给后端进行解析。

博主在爬虫时遇到的就是 Content-Type:application/json 的情况,如图3-1:

图3-1

第二个红框也不像前两个一样是 Form Data 而是变成了 Request Payload ,其中的数据也是经过浏览器解析的,原始数据如图3-2:

图3-2

图3-2

可以看出来,数据确实是以json格式进行传输的。

如果我们想模拟这种请求,如下代码是不行的:

            
              
                import
              
               requests


headers 
              
                =
              
              
                {
              
              
                'Content-Type'
              
              
                :
              
              
                'application/json'
              
              
                ,
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                }
              
              

data 
              
                =
              
              
                {
              
              
                "n"
              
              
                :
              
              
                "测试logo"
              
              
                ,
              
              
                "s"
              
              
                :
              
              
                "TEST LOGO"
              
              
                ,
              
              
                "descr"
              
              
                :
              
              
                "this is demo"
              
              
                ,
              
              
                "data"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "p"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "dataPage"
              
              
                :
              
              
                0
              
              
                ,
              
              
                "icon_lists"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "icon_page"
              
              
                :
              
              
                1
              
              
                }
              
              

url 
              
                =
              
              
                'https://www.logosc.cn/api/getAllInfo'
              
              
response 
              
                =
              
               requests
              
                .
              
              post
              
                (
              
              url
              
                =
              
              url
              
                ,
              
               data
              
                =
              
              data
              
                ,
              
               headers
              
                =
              
              headers
              
                )
              
              
                print
              
              
                (
              
              response
              
                .
              
              json
              
                (
              
              
                )
              
              
                )
              
            
          

根据请求的URL不同,报错信息也会一样,但无一例外的请求失败,如图3-3:

图3-3

遇到Request Payload的解决办法

碰到问题,我们首先求助的应该是官方文档,文档建议如下图4-1:

Python爬虫遇到Request-Payload怎么办?_第2张图片

图4-1

官方提供了两种方法让我们以 application/json 格式编码数据进行传输。

1.使用json.dumps()方法

json.dumps()方法将字典数据转化成json类型然后传给data参数,代码如下:

            
              
                import
              
               requests

              
                import
              
               json

 headers 
              
                =
              
              
                {
              
              
                'Content-Type'
              
              
                :
              
              
                'application/json'
              
              
                ,
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                }
              
              
 data 
              
                =
              
              
                {
              
              
                "n"
              
              
                :
              
              
                "测试logo"
              
              
                ,
              
              
                "s"
              
              
                :
              
              
                "TEST LOGO"
              
              
                ,
              
              
                "descr"
              
              
                :
              
              
                "this is demo"
              
              
                ,
              
              
                "data"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "p"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "dataPage"
              
              
                :
              
              
                0
              
              
                ,
              
              
                "icon_lists"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "icon_page"
              
              
                :
              
              
                1
              
              
                }
              
              
 url 
              
                =
              
              
                'https://www.logosc.cn/api/getAllInfo'
              
              
 response 
              
                =
              
               requests
              
                .
              
              post
              
                (
              
              url
              
                =
              
              url
              
                ,
              
               data
              
                =
              
              json
              
                .
              
              dumps
              
                (
              
              data
              
                )
              
              
                ,
              
               headers
              
                =
              
              headers
              
                )
              
              
                print
              
              
                (
              
              response
              
                .
              
              json
              
                (
              
              
                )
              
              
                )
              
            
          

2.将数据传给json参数

requests.post方法里有个json参数,当我们把数据传给json参数时,Content-Type会被自动的设置成application/json,代码如下:

            
              
                import
              
               requests
 headers 
              
                =
              
              
                {
              
              
                'Content-Type'
              
              
                :
              
              
                'application/json'
              
              
                ,
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                .
              
              
                }
              
              
 data 
              
                =
              
              
                {
              
              
                "n"
              
              
                :
              
              
                "测试logo"
              
              
                ,
              
              
                "s"
              
              
                :
              
              
                "TEST LOGO"
              
              
                ,
              
              
                "descr"
              
              
                :
              
              
                "this is demo"
              
              
                ,
              
              
                "data"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "p"
              
              
                :
              
              
                1
              
              
                ,
              
              
                "dataPage"
              
              
                :
              
              
                0
              
              
                ,
              
              
                "icon_lists"
              
              
                :
              
              
                [
              
              
                ]
              
              
                ,
              
              
                "icon_page"
              
              
                :
              
              
                1
              
              
                }
              
              
 url 
              
                =
              
              
                'https://www.logosc.cn/api/getAllInfo'
              
              
 response 
              
                =
              
               requests
              
                .
              
              post
              
                (
              
              url
              
                =
              
              url
              
                ,
              
               json
              
                =
              
              data
              
                ,
              
               headers
              
                =
              
              headers
              
                )
              
              
                print
              
              
                (
              
              response
              
                .
              
              json
              
                (
              
              
                )
              
              
                )
              
            
          

结尾语

今天又爬出了一个小坑,很是开心,如果本文对你有所帮助,欢迎关注下方公众号「猿天罡」,不定期更新Python和算法相关的文章。see you!
Python爬虫遇到Request-Payload怎么办?_第3张图片


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论