├── 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 | ![](screenshots/2.png) 9 | ### Charles中如何找到原始http请求: 10 | ![](screenshots/3.png) 11 | ### 示例截图: 12 | ![](screenshots/1.png) 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 --------------------------------------------------------------------------------