本文地址:https://blog.csdn.net/dietime1943/article/details/87312903
本文作者:bluetata [email protected]
****** 如果你看到这一行,说明网络爬虫可能在本人还没有发布完成的时候就抓走了我的文章,导致内容不完整,请去上述的原文链接查看原文 ******
本文章意在讲解如何使用Post请求Request payload类型的form提交,以及如何使用Jsoup进行上传文件。
本文大纲如下:
1. 关于Request Payload(请求负载) 的解释说明
2. 使用Jsoup提交Json类型的Request Payload(请求负载)
3. 使用Jsoup提交multipart/form-data类型的Request Payload(请求负载) / 使用Jsoup上传文件
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
Request Payload(请求负载):payload body of a HTTP Request 通常在传输数据时,为了使数据传输更可靠,要把原始数据分批传输,并且在每一批数据的头和尾都加上一定的辅助信息,比如这一批数据量的大小,校验位等,这样就相当于给已经分批原始数据加一些外套,这些外套起到标示作用,使得原始数据不易丢失。一批数据加上它的“外套”,就形成了传输通道中基本的传输单元(数据帧或者数据包)。消息体就是“外套”,即标记着原始数据的大小等的辅助信息。传输单元中的原始数据就是有效负载数据。
通常在发送POST,PUT和PATCH请求的时候才可以携带Payload数据。
如果一个请求为:Content-Type: application/json 类型,它的请求格式类似于:
POST /some-path HTTP/1.1
Content-Type: application/json
{ "username" : "sekito", "password" : "password123" }
另一种,如果一个请求方式为POST,请求类型为 Content-Type: application/x-www-form-urlencoded 或者 Content-Type: multipart/form-data,请求格式类似于:
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=sekito&password=password123
而在复合数据类型(multipart/form-data)提交的时候,你在F12开发者工具看到的类似于如下格式:
------WebKitFormBoundaryO5quBRiT4G7Vm3R7
Content-Disposition: form-data; name="message"
Hello World
------WebKitFormBoundaryO5quBRiT4G7Vm3R7
Content-Disposition: form-data; name="file"; filename="Test.txt"
Content-Type: text/plain
aaaTest
------WebKitFormBoundaryO5quBRiT4G7Vm3R7--
针对multipart/form-data类型提交请求的时候,F12看到的格式解释如下:
第一段数据的Key为 name="message" 中的 "message",value为 "Hello World"
第二段数据的Key为 name="file" 中的 "file",file名为 "Test.txt",文件中的内容为:"aaaTest"。
解释完Payload相关,下面会分别从json形式 和 multipart/form-data 形式的request payload 做模拟请求
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
比较常见的一种Json形式Request Payload提交请求的例子就是在分页的时候,post提交分页请求,一般为json传递:
该网站即为比较典型的动态分页,且提交数据为Request Payload的形式,这种Json格式的提交,早在[Jsoup] 如何发送Json请求(how to send json by Jsoup) 一文中详细介绍过,这里只针对该情况写出模拟示例(本示例使用的阿里的fastjson):
JSONObject payload = new JSONObject();
// {"pageIndex":2,"pageSize":20,"typeTab":1}
payload.put("pageIndex", 2);
payload.put("pageSize", 20);
payload.put("typeTab", 1);
// String jsonBody = "{\"name\":\"ACTIVATE\",\"value\":\"E0010\"}";
Connection connection = Jsoup.connect("https://www.tablenow.vn/ho-chi-minh/bo-suu-tap")
.userAgent("Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36") // User-Agent of Chrome 55
.referrer("https://www.tablenow.vn/ho-chi-minh/bo-suu-tap")
.header("Content-Type", "application/json;charset=UTF-8")
.header("Accept", "application/json, text/plain, */*")
.header("Accept-Encoding", "gzip, deflate, br")
.header("Accept-Language", "zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7")
.header("Connection", "keep-alive")
.requestBody(payload.toJSONString())
.maxBodySize(100)
.timeout(1000 * 10)
.method(Connection.Method.POST);
Response response = connection.execute();
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
在下图Request headers中可以看到,Content-Type为:multipart/form-data; boundary=--------------------2043647828081
这里的 "boundary=--------------------2043647828081" 的主要作用是分隔作用,用于指定数据的封装边界。关于boundary参数更多解释可以参照stack overflow中What is the boundary parameter in an HTTP multi-part (POST) Request?中指向的W3C解释链接。
对于带有boundary分隔数据的Request payload请求提交,Jsoup现在一般有3种思路:一种将F12开发者工具中看到的request payload看做是一个字符串,之后根据自己想要动态赋值value,来动态拼接一个和F12看到一模一样的字符串,之后将该字符串传递到requestBody中,另一种是将该字符串拆解成一个json对象,之后类似于上文提到过的按照json形式来提交。注意:以上该两种方式均为非upload数据流的request payload请求负载。
此文重点讲述第三种带有文件上传的方式,如果想查看上述两种的,请查看GitHub上提交的源码。
对于第三种Jsoup进行multipart/form-data的请求,在Jsoup 1.8.2 (Apr 13, 2015)前是不支持的,在 Jsoup 1.8.2 的时候提供了一个上传文件的API:data(String, String, InputStream),如果非要使用Jsoup 1.8.2之前的jar,那么可以考虑利用HttpClient进行模拟提交。
下图举例来说明:
在页面中可以看到第一个数据部分为一个input,其中name为:"text",其value为:"Jsoup upload",第二个数据部分为,一个上传选择框,其name为:"file1",上传的文件名为:"uploadTest.txt",文件里的内容为:"dump text"。
请求示例代码为:
// upload file by jsoup
File file1 = new File("C:/dir/file1.txt");
FileInputStream fs1 = new FileInputStream(file1);
Response response1 = Jsoup.connect("http://bluetata.com/")
.data("text","Jsoup upload") // 绑定数据
.data("file1", "uploadTest.txt", fs1) // 上传文件
.method(Method.POST)
.execute();
reflink:
[Jsoup] 如何发送Json请求(how to send json by Jsoup)
What's the difference between “Request Payload” vs “Form Data” as seen in Chrome dev tools Network tab
https://javarush.ru/groups/posts/1429-jsoup--multipartform-data-response
https://www.yoheim.net/blog.php?q=20120611
https://www.yoheim.net/blog.php?q=20171201
● Jsoup学习讨论QQ群:50695115
● Jsoup爬虫代码示例及博客内源码下载:https://github.com/bluetata/crawler-jsoup-maven
● 更多Jsoup相关文章,请查阅专栏:【Jsoup in action】
注:本文原创由`bluetata`发布于blog.csdn.net、转载请务必注明出处。