重构蓝奏云解析代码, 加入蓝奏云加密分享解析

This commit is contained in:
QAIU
2023-06-12 10:39:33 +08:00
parent 5d23c57d0e
commit 8b6075af37
3 changed files with 83 additions and 164 deletions

View File

@@ -1,21 +1,14 @@
package cn.qaiu.lz.common.util; package cn.qaiu.lz.common.util;
import com.fasterxml.jackson.core.type.TypeReference; import cn.qaiu.vx.core.util.VertxHolder;
import com.fasterxml.jackson.databind.ObjectMapper; import io.vertx.core.Future;
import io.vertx.core.MultiMap; import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject; import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions; import io.vertx.ext.web.client.WebClientOptions;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -27,159 +20,71 @@ import java.util.regex.Pattern;
*/ */
public class LzTool { public class LzTool {
public static String parse(String fullUrl) throws Exception { public static final String SHARE_URL_PREFIX = "https://wwwa.lanzoui.com";
var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0" +
".3626.121 Safari/537.3";
var url = fullUrl.substring(0, fullUrl.lastIndexOf('/') + 1);
var id = fullUrl.substring(fullUrl.lastIndexOf('/') + 1);
Map<String, String> header = new HashMap<>();
header.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
header.put("referer", url);
/* public static Future<String> parse(String data, String code) {
// 部分链接需要设置安卓UA Promise<String> promise = Promise.promise();
sec-ch-ua: "Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111" String key = data.indexOf('/') > 0 ? data : SHARE_URL_PREFIX + "/" + data;
sec-ch-ua-mobile: ?1
sec-ch-ua-platform: "Android"
*/
var userAgent2 = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like " +
"Gecko) Chrome/111.0.0.0 Mobile Safari/537.36";
Map<String, String> header2 = new HashMap<>();
header2.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
header2.put("sec-ch-ua-mobile", "sec-ch-ua-mobile");
header2.put("sec-ch-ua-platform", "Android");
header2.put("referer", url);
//第一次请求获取iframe的地址 WebClient client = WebClient.create(VertxHolder.getVertxInstance(),
String result = Jsoup.connect(url + id) new WebClientOptions().setFollowRedirects(false));
.userAgent(userAgent)
.get()
.select(".ifr2")
.attr("src");
//第二次请求得到js里的json数据里的sign
result = Jsoup.connect(url + result)
.headers(header)
.userAgent(userAgent)
.get()
.html();
// System.out.println(result);
// 'sign':'AWcGOFprUGFWX1BvBTVXawdrBDZTOAU_bV2FTZFU7W2sBJ1t4DW0FYFIyBmgDZVJgUjAFNV41UGQFNg_c_c' 改下正则TMD
// 最近上传竟然没_c_c
Matcher matcher = Pattern.compile("'sign'\s*:\s*'([0-9a-zA-Z_]+)'").matcher(result);
Map<String, String> params = new LinkedHashMap<>();
if (matcher.find()) {
String sn = matcher.group(1).replace("'", "");
params.put("action", "downprocess");
params.put("sign", sn);
params.put("ves", "1");
// System.out.println(sn);
} else {
throw new IOException();
}
//第三次请求 通过参数发起post请求,返回json数据
result = Jsoup
.connect(url + "ajaxm.php")
.headers(header)
.userAgent(userAgent)
.data(params)
.post()
.text()
.replace("\\", "");
//json转为map
params = new ObjectMapper().readValue(result, new TypeReference<>() {
});
// System.out.println(params);
//通过json的数据拼接出最终的URL发起第最终请求,并得到响应信息头
url = params.get("dom") + "/file/" + params.get("url");
var headers = Jsoup.connect(url)
.ignoreContentType(true)
.userAgent(userAgent2)
.headers(header2)
.followRedirects(false)
.execute()
.headers();
//得到重定向的地址进行重定向
url = headers.get("Location");
return url;
}
public static void main(String[] args) {
// String key = "https://wwsd.lanzoue.com/iNvid035jgcb";
String key = "https://wwsd.lanzoue.com/icBp6qqj82b";
String urlPrefix = "https://lanzoux.com";
String code = "QAIU";
WebClient client = WebClient.create(Vertx.vertx(), new WebClientOptions().setFollowRedirects(false));
client.getAbs(key).send().onSuccess(res -> { client.getAbs(key).send().onSuccess(res -> {
String html = res.bodyAsString(); String html = res.bodyAsString();
// 匹配iframe // 匹配iframe
Pattern compile = Pattern.compile("class=\"ifr2\" name=.+src=\"(/fn\\?[a-zA-Z0-9_+/=]{16,})\""); Pattern compile = Pattern.compile("src=\"(/fn\\?[a-zA-Z0-9_+/=]{16,})\"");
Matcher matcher = compile.matcher(html); Matcher matcher = compile.matcher(html);
if (!matcher.find()) { if (!matcher.find()) {
// $.ajax({ // 没有Iframe说明是加密分享, 匹配sign通过密码请求下载页面
// type : 'post',
// url : '/ajaxm.php',
// //data : 'action=downprocess&sign=VTMAPgs6UG&p='+pwd,
// data : 'action=downprocess&sign
// =VzEBPwAxBzYIAQo1BjYBPVA_bDj1fNgEwUWNTYFUwAzMJL1V2Xj5XMlMzVjhTMVFjUzEHOlM4AjEBNQ_c_c&p
// ='+pwd,
// //data : 'action=downprocess&sign=VTMAPgs6UG&p='+pwd,
// dataType : 'json',
// success:function(msg){
// var date = msg;
// if(date.zt == '1'){
// $("#downajax").html("<a href="+date.dom+"/file/"+ date.url +" target=_blank
// rel=noreferrer>下载</a>");
// }else{
// $("#info").text(date.inf);
// };
//
// },
// 匹配不到说明需要密码 直接解析并请求ajaxm.php
// 匹配sign
Pattern compile2 = Pattern.compile("sign=([0-9a-zA-Z_]{16,})"); Pattern compile2 = Pattern.compile("sign=([0-9a-zA-Z_]{16,})");
Matcher matcher2 = compile2.matcher(html); Matcher matcher2 = compile2.matcher(html);
if (!matcher2.find()) { if (!matcher2.find()) {
promise.fail(key + ": sign正则匹配失败, 可能分享已失效: " + html);
return; return;
} }
String sign = matcher2.group(1); String sign = matcher2.group(1);
getDownURL(promise, code, key, client, sign);
var userAgent2 = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, " +
"like " +
"Gecko) Chrome/111.0.0.0 Mobile Safari/537.36";
HttpRequest<Buffer> bufferHttpRequest = client.postAbs(urlPrefix + "/ajaxm.php");
bufferHttpRequest.putHeader("User-Agent", userAgent2);
bufferHttpRequest.putHeader("referer", key);
bufferHttpRequest.putHeader("sec-ch-ua-platform", "Android");
bufferHttpRequest.putHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
bufferHttpRequest.putHeader("sec-ch-ua-mobile", "sec-ch-ua-mobile");
bufferHttpRequest.sendForm(MultiMap.caseInsensitiveMultiMap()
.set("action", "downprocess")
.set("sign", sign).set("p", code)).onSuccess(res2 -> {
JsonObject urlJson = res2.bodyAsJsonObject();
System.out.println(urlJson);
String downUrl = urlJson.getString("dom") + "/file/" + urlJson.getString("url");
System.out.println(downUrl);
client.getAbs(downUrl).send().onSuccess(res3 -> {
System.out.println(res3.headers());
System.out.println(res3.bodyAsString());
});
});
return; return;
} }
String iframePath = matcher.group(1); String iframePath = matcher.group(1);
System.out.println(iframePath); client.getAbs(SHARE_URL_PREFIX + iframePath).send().onSuccess(res2 -> {
client.getAbs(urlPrefix + iframePath).send().onSuccess(res2 -> { String html2 = res2.bodyAsString();
System.out.println(res2.bodyAsString()); System.out.println(html);
Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'([0-9a-zA-Z_]+)'").matcher(html2);
if (!matcher2.find()) {
promise.fail(SHARE_URL_PREFIX + iframePath + " -> " + key + ": sign正则匹配失败, 可能分享已失效: " + html2);
return;
}
String sign = matcher2.group(1);
getDownURL(promise, code, key, client, sign);
}); });
}); });
return promise.future();
}
private static void getDownURL(Promise<String> promise, String code, String key, WebClient client, String sign) {
MultiMap headers = MultiMap.caseInsensitiveMultiMap();
var userAgent2 = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, " +
"like " +
"Gecko) Chrome/111.0.0.0 Mobile Safari/537.36";
headers.set("User-Agent", userAgent2);
headers.set("referer", key);
headers.set("sec-ch-ua-platform", "Android");
headers.set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
headers.set("sec-ch-ua-mobile", "sec-ch-ua-mobile");
client.postAbs(SHARE_URL_PREFIX + "/ajaxm.php").putHeaders(headers).sendForm(MultiMap
.caseInsensitiveMultiMap()
.set("action", "downprocess")
.set("sign", sign).set("p", code)).onSuccess(res2 -> {
JsonObject urlJson = res2.bodyAsJsonObject();
if (urlJson.getInteger("zt") != 1) {
promise.fail(urlJson.getString("inf"));
return;
}
String downUrl = urlJson.getString("dom") + "/file/" + urlJson.getString("url");
client.getAbs(downUrl).putHeaders(headers).send().onSuccess(res3 -> {
promise.complete(res3.headers().get("Location"));
});
});
} }
} }

View File

@@ -70,12 +70,11 @@ public class ServerApi {
promise.complete(); promise.complete();
}).onFailure(t -> promise.fail(t.fillInStackTrace())); }).onFailure(t -> promise.fail(t.fillInStackTrace()));
} else if (url.contains("lanzou")) { } else if (url.contains("lanzou")) {
String urlDownload;
try { try {
urlDownload = LzTool.parse(url); LzTool.parse(url, pwd).onSuccess(resUrl -> {
log.info("url = {}", urlDownload); response.putHeader("location", resUrl).setStatusCode(302).end();
response.putHeader("location", urlDownload).setStatusCode(302).end(); promise.complete();
promise.complete(); }).onFailure(t -> promise.fail(t.fillInStackTrace()));
} catch (Exception e) { } catch (Exception e) {
promise.fail(e); promise.fail(e);
} }
@@ -94,11 +93,30 @@ public class ServerApi {
} }
@RouteMapping(value = "/lz/:id", method = RouteMethod.GET) @RouteMapping(value = "/lz/:id", method = RouteMethod.GET)
public void lzParse(HttpServerResponse response, String id) throws Exception { public void lzParse(HttpServerResponse response, String id) {
var url = "https://wwsd.lanzoue.com/" + id; String code = "";
var urlDownload = LzTool.parse(url); if (id.contains("@")) {
log.info("url = {}", urlDownload); String[] ids = id.split("@");
response.putHeader("location", urlDownload).setStatusCode(302).end(); id = ids[0];
code = ids[1];
}
LzTool.parse(id, code).onSuccess(resUrl -> response.putHeader("location", resUrl)
.setStatusCode(302).end()).onFailure(t -> {
response.putHeader(CONTENT_TYPE, "text/html;charset=utf-8");
response.end(t.getMessage());
});
}
@RouteMapping(value = "/json/lz/:id", method = RouteMethod.GET)
public Future<String> lzParseJson(HttpServerResponse response, String id) {
String code = "";
if (id.contains("@")) {
String[] ids = id.split("@");
id = ids[0];
code = ids[1];
}
return LzTool.parse(id, code);
} }
@RouteMapping(value = "/cow/:id", method = RouteMethod.GET) @RouteMapping(value = "/cow/:id", method = RouteMethod.GET)
@@ -108,14 +126,6 @@ public class ServerApi {
response.putHeader("location", urlDownload).setStatusCode(302).end(); response.putHeader("location", urlDownload).setStatusCode(302).end();
} }
@RouteMapping(value = "/json/lz/:id", method = RouteMethod.GET)
public JsonResult<String> lzParseJson(HttpServerResponse response, String id) throws Exception {
var url = "https://wwsd.lanzoue.com/" + id;
var urlDownload = LzTool.parse(url);
log.info("url = {}", urlDownload);
return JsonResult.data(urlDownload);
}
@RouteMapping(value = "/json/cow/:id", method = RouteMethod.GET) @RouteMapping(value = "/json/cow/:id", method = RouteMethod.GET)
public JsonResult<String> cowParseJson(HttpServerResponse response, String id) throws Exception { public JsonResult<String> cowParseJson(HttpServerResponse response, String id) throws Exception {
var url = "https://cowtransfer.com/s/" + id; var url = "https://cowtransfer.com/s/" + id;

View File

@@ -16,7 +16,11 @@ GET http://127.0.0.1:6400/cow/9a644fe3e3a748
### ###
# @no-redirect # @no-redirect
GET http://127.0.0.1:6400/lz/ia2cntg GET http://127.0.0.1:6400/lz/i6SqHmp1yfc
###
# @no-redirect
GET http://127.0.0.1:6400/lz/icBp6qqj82b@QAIU
### ###
GET http://127.0.0.1:6400/json/lz/ia2cntg GET http://127.0.0.1:6400/json/lz/ia2cntg