├── HttpRaw2Jsoup.iml
├── LICENSE
├── README.md
├── pom.xml
├── screenshots
├── 1.png
├── 2.png
└── 3.png
└── src
└── main
└── java
└── me
└── kagura
├── Controller.java
├── HttpRaw2Jsoup.fxml
├── Main.java
├── Service.java
└── logo_x72.png
/HttpRaw2Jsoup.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 鹞之神乐
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HttpRaw2Jsoup
2 |
3 | #### 本工具可以帮你把原生http请求转换成Jsoup请求代码,方便爬虫编写,接口测试。
4 | #### 直接粘贴原始请求即可生成代码并自动复制到剪切板,支持跨平台。
5 | ### 如何使用?
6 | #### 下载[HttpRaw2Jsoup-1.6.jar](https://github.com/KingFalse/HttpRaw2Jsoup/releases/download/v1.6/HttpRaw2Jsoup-1.6.jar),双击运行即可使用
7 | ### Fiddler中如何找到原始http请求:
8 | 
9 | ### Charles中如何找到原始http请求:
10 | 
11 | ### 示例截图:
12 | 
13 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | me.kagura
6 | HttpRaw2Jsoup
7 | 1.6
8 |
9 |
10 |
11 | org.apache.maven.plugins
12 | maven-compiler-plugin
13 |
14 | 1.8
15 | 1.8
16 |
17 |
18 |
19 | org.apache.maven.plugins
20 | maven-jar-plugin
21 |
22 | target/classes/
23 |
24 |
25 |
26 | me.kagura.Main
27 |
28 |
29 |
30 |
31 |
32 |
33 | .
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | false
42 | src/main/java
43 |
44 | **/*.fxml
45 | **/*.png
46 |
47 |
48 |
49 |
50 |
51 | jar
52 |
53 | HttpRaw2Jsoup
54 | http://maven.apache.org
55 |
56 |
57 | UTF-8
58 | UTF-8
59 | 1.8
60 |
61 |
62 |
63 |
64 | junit
65 | junit
66 | 3.8.1
67 | test
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KingFalse/HttpRaw2Jsoup/1d771f00c18810708380c2ceb2be93fb1540c5f0/screenshots/1.png
--------------------------------------------------------------------------------
/screenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KingFalse/HttpRaw2Jsoup/1d771f00c18810708380c2ceb2be93fb1540c5f0/screenshots/2.png
--------------------------------------------------------------------------------
/screenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KingFalse/HttpRaw2Jsoup/1d771f00c18810708380c2ceb2be93fb1540c5f0/screenshots/3.png
--------------------------------------------------------------------------------
/src/main/java/me/kagura/Controller.java:
--------------------------------------------------------------------------------
1 | package me.kagura;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.TextArea;
5 | import javafx.scene.input.Clipboard;
6 | import javafx.scene.input.ClipboardContent;
7 | import javafx.scene.input.KeyEvent;
8 |
9 | public class Controller {
10 |
11 | @FXML
12 | TextArea input;
13 |
14 | @FXML
15 | TextArea output;
16 |
17 | Service service = new Service();
18 |
19 | public void inputOnKeyReleased(KeyEvent keyEvent) {
20 | if ((keyEvent.isControlDown() || keyEvent.isMetaDown()) && keyEvent.getText().equalsIgnoreCase("v")) {
21 | try {
22 | input.selectPositionCaret(0);
23 | output.clear();
24 |
25 | String generateResult = service.doGenerate(input.getText());
26 | output.setText(generateResult);
27 | //将生成的代码放入剪切板
28 | try {
29 | Clipboard clipboard = Clipboard.getSystemClipboard();
30 | ClipboardContent cc = new ClipboardContent();
31 | cc.putString(generateResult);
32 | clipboard.setContent(cc);
33 | } catch (Exception exx) {
34 | exx.printStackTrace();
35 | }
36 | } catch (Exception e) {
37 | e.printStackTrace();
38 | output.setText("发生异常:" + e.getLocalizedMessage());
39 | }
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/me/kagura/HttpRaw2Jsoup.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/main/java/me/kagura/Main.java:
--------------------------------------------------------------------------------
1 | package me.kagura;
2 |
3 | import javafx.application.Application;
4 | import javafx.fxml.FXMLLoader;
5 | import javafx.scene.Parent;
6 | import javafx.scene.Scene;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 |
10 | public class Main extends Application {
11 |
12 | public static void main(String[] args) {
13 | launch(args);
14 | }
15 |
16 | @Override
17 | public void start(Stage primaryStage) throws Exception {
18 | Parent root = FXMLLoader.load(getClass().getResource("HttpRaw2Jsoup.fxml"));
19 | primaryStage.setTitle("HttpRaw2Jsoup v1.6");
20 | primaryStage.setScene(new Scene(root));
21 | primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("logo_x72.png")));
22 | primaryStage.show();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/me/kagura/Service.java:
--------------------------------------------------------------------------------
1 | package me.kagura;
2 |
3 | import java.net.URLDecoder;
4 | import java.util.HashMap;
5 | import java.util.Map;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | public class Service {
10 | //HTTP方法
11 | public static String[] methods = new String[]{"POST", "GET", "OPTIONS", "HEAD", "PUT", "DELETE", "TRACE", "CONNECT"};
12 | //最终生成的代码
13 | public static String generateCode = "";
14 | public String contentType = "";
15 |
16 | public String doGenerate(String rawString) throws Exception {
17 | generateCode = "";
18 | //解析出请求方法
19 | String method = "";
20 | for (String key : methods) {
21 | if (rawString.matches("\\s*" + key + " [\\d\\D]*")) {
22 | method = key;
23 | break;
24 | }
25 | }
26 | if (method.isEmpty()) {
27 | return "非标准HTTP RAW内容!";
28 | }
29 |
30 | //解析出请求链接
31 | String absUrl = "";
32 | Pattern pattern = Pattern.compile("\\s*" + method + " ([\\d\\D]*) HTTP/\\d\\.?\\d?\\s");
33 |
34 | Matcher matcher = pattern.matcher(rawString);
35 | matcher.find();
36 | absUrl = matcher.group(1);
37 |
38 | //去除请求行
39 | rawString = rawString.replace(matcher.group(), "");
40 |
41 | //处理请求头
42 | String[] headers = rawString.contains("\r\n") ? rawString.split("\r\n") : rawString.split("\n");
43 | Map headersMap = new HashMap<>();
44 | String cookiesStr = "";
45 | String body = "";
46 | for (int i = 0; i < headers.length; i++) {
47 | String header = headers[i];
48 | if (header.isEmpty() && i < headers.length - 1) {
49 | body = headers[i + 1];
50 | break;
51 | }
52 | pattern = Pattern.compile("([\\d\\D]+):\\s+([\\d\\D]*)");
53 | matcher = pattern.matcher(header);
54 | matcher.find();
55 | String key = matcher.group(1);
56 | String val = "";
57 | try {
58 | val = matcher.group(2);
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | }
62 |
63 | if (key.equals("Cookie")) {
64 | cookiesStr = val;
65 | continue;
66 | }
67 |
68 | headersMap.put(key, val.replaceAll("\"", "\\\\\""));
69 | if (key.equals("Content-Type")) {
70 | contentType = val;
71 | }
72 | }
73 |
74 | //处理Cookie
75 | cookiesStr = URLDecoder.decode(cookiesStr,"UTF-8");
76 | String[] cookiesArray = cookiesStr.split(";");
77 | Map cookieMap = new HashMap<>();
78 | for (String cookie : cookiesArray) {
79 | if (cookie.isEmpty()) {
80 | continue;
81 | }
82 | int first = cookie.indexOf("=");
83 | cookieMap.put(cookie.substring(0, first), cookie.substring(first + 1, cookie.length()));
84 | }
85 |
86 | //处理请求体
87 | Map bodyMap = new HashMap<>();
88 | String bodyJson = "";
89 | if (contentType.contains("form")) {
90 | //提交方式为表单
91 | String decodeBody = URLDecoder.decode(body, "UTF-8");
92 | if (!decodeBody.isEmpty() && !decodeBody.equals("")) {
93 | String[] formArray = decodeBody.split("&");
94 | for (String formItem : formArray) {
95 | String[] split = formItem.split("=");
96 | bodyMap.put(split[0], split.length == 1 ? "" : split[1].replaceAll("\"", "\\\\\""));
97 | }
98 | }
99 |
100 | } else if (contentType.contains("json")) {
101 | //提交方式为JSON提交方式为JSON
102 | String decodeBody = URLDecoder.decode(body, "UTF-8");
103 | bodyJson = decodeBody;
104 |
105 | }
106 |
107 | //生成代码
108 | generateCode = generateCode += String.format("Connection.Response response = Jsoup.connect(\"%s\")", absUrl) + System.lineSeparator();
109 | generateCode = generateCode += String.format(".method(%s)", "Connection.Method." + method) + System.lineSeparator();
110 | if (!cookieMap.isEmpty()) {
111 | generateCode = generateCode += ".cookies(new HashMap() {{" + System.lineSeparator();
112 | cookieMap.forEach((key, val) -> {
113 | generateCode = generateCode += String.format(" put(\"%s\", \"%s\");", key, val) + System.lineSeparator();
114 | });
115 | generateCode = generateCode += "}})" + System.lineSeparator();
116 | }
117 |
118 | generateCode = generateCode += ".headers(new HashMap() {{" + System.lineSeparator();
119 | headersMap.forEach((key, val) -> {
120 | generateCode = generateCode += String.format(" put(\"%s\", \"%s\");", key, val) + System.lineSeparator();
121 | });
122 | generateCode = generateCode += "}})" + System.lineSeparator();
123 |
124 | if (contentType.contains("form")) {
125 | if (!bodyMap.isEmpty()) {
126 | //表单方式
127 | generateCode = generateCode += ".data(new HashMap() {{" + System.lineSeparator();
128 | bodyMap.forEach((key, val) -> {
129 | generateCode = generateCode += String.format(" put(\"%s\", \"%s\");", key, val) + System.lineSeparator();
130 | });
131 | generateCode = generateCode += "}})" + System.lineSeparator();
132 | }
133 | } else if (contentType.contains("json")) {
134 | //JSON方式
135 | generateCode = generateCode += String.format(".requestBody(\"%s\")", bodyJson.replaceAll("\"", "\\\\\"")) + System.lineSeparator();
136 | }
137 | generateCode = generateCode += ".validateTLSCertificates(false)" + System.lineSeparator();
138 | generateCode = generateCode += ".ignoreContentType(true)" + System.lineSeparator();
139 | generateCode = generateCode += ".execute();" + System.lineSeparator();
140 | generateCode = generateCode += "\t//获取返回的原始body (字符串)" + System.lineSeparator();
141 | generateCode = generateCode += "String body = response.body();" + System.lineSeparator();
142 | generateCode = generateCode += "\t//将response转换为html Document" + System.lineSeparator();
143 | generateCode = generateCode += "Document document = response.parse();" + System.lineSeparator();
144 | generateCode = generateCode += "\t//将response转换为xml Document" + System.lineSeparator();
145 | generateCode = generateCode += "Document xmlDocument = Jsoup.parse(response.body(), response.parse().baseUri(), Parser.xmlParser());" + System.lineSeparator();
146 | generateCode = generateCode += "\t//将response转换为Base64结构的验证码字符串" + System.lineSeparator();
147 | generateCode = generateCode += "String responseToBase64Img = response == null ? null : \"data:image/jpeg;base64,\" + Base64.getEncoder().encodeToString(response.bodyAsBytes());" + System.lineSeparator();
148 | generateCode = generateCode += "\t//获取返回的BufferedInputStream" + System.lineSeparator();
149 | generateCode = generateCode += "BufferedInputStream bufferedInputStream = response.bodyStream();" + System.lineSeparator();
150 |
151 | return generateCode;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/main/java/me/kagura/logo_x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KingFalse/HttpRaw2Jsoup/1d771f00c18810708380c2ceb2be93fb1540c5f0/src/main/java/me/kagura/logo_x72.png
--------------------------------------------------------------------------------