[Jsoup] 使用Jsoup發送Request Payload(請求負載)

本文地址: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上傳文件

1. 關於 Request Payload(請求負載) 的解釋說明

Request Payload(請求負載):payload body of a HTTP Request 通常在傳輸數據時,爲了使數據傳輸更可靠,要把原始數據分批傳輸,並且在每一批數據的頭和尾都加上一定的輔助信息,比如這一批數據量的大小,校驗位等,這樣就相當於給已經分批原始數據加一些外套,這些外套起到標示作用,使得原始數據不易丟失。一批數據加上它的“外套”,就形成了傳輸通道中基本的傳輸單元(數據幀或者數據包)。消息體就是“外套”,即標記着原始數據的大小等的輔助信息傳輸單元中的原始數據就是有效負載數據

通常在發送POSTPUTPATCH請求的時候纔可以攜帶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 做模擬請求

2. 使用Jsoup提交Json類型的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();

3. 使用Jsoup提交multipart/form-data類型的Request Payload(請求負載) / 使用Jsoup上傳文件

在下圖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、轉載請務必註明出處。

Flag Counter

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章