mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-04-10 19:06:55 +00:00
LzToooool
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<groupId>cn.qaiu</groupId>
|
<groupId>cn.qaiu</groupId>
|
||||||
<artifactId>parser</artifactId>
|
<artifactId>parser</artifactId>
|
||||||
<version>10.2.3</version>
|
<version>10.2.5</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>cn.qaiu:parser</name>
|
<name>cn.qaiu:parser</name>
|
||||||
|
|||||||
@@ -68,42 +68,41 @@ public enum PanDomainTemplate {
|
|||||||
t-is.cn
|
t-is.cn
|
||||||
*/
|
*/
|
||||||
LZ("蓝奏云",
|
LZ("蓝奏云",
|
||||||
compile("https://(?:[a-zA-Z\\d-]+\\.)?(" +
|
compile("https://(?:[a-zA-Z\\d-]+\\.)?(" +
|
||||||
"lanzoul|" +
|
"lanzoul|" +
|
||||||
"lanzouh|" +
|
"lanzouh|" +
|
||||||
"lanosso|" +
|
"lanosso|" +
|
||||||
"lanpv|" +
|
"lanpv|" +
|
||||||
"bakstotre|" +
|
"bakstotre|" +
|
||||||
"lanzouo|" +
|
"lanzouo|" +
|
||||||
"lanzov|" +
|
"lanzov|" +
|
||||||
"lanpw|" +
|
"lanpw|" +
|
||||||
"ulanzou|" +
|
"ulanzou|" +
|
||||||
"lanzouf|" +
|
"lanzouf|" +
|
||||||
"lanzn|" +
|
"lanzn|" +
|
||||||
"lanzouj|" +
|
"lanzouj|" +
|
||||||
"lanzouk|" +
|
"lanzouk|" +
|
||||||
"lanzouq|" +
|
"lanzouq|" +
|
||||||
"lanzouv|" +
|
"lanzouv|" +
|
||||||
"lanzoue|" +
|
"lanzoue|" +
|
||||||
"lanzouw|" +
|
"lanzouw|" +
|
||||||
"lanzoub|" +
|
"lanzoub|" +
|
||||||
"lanzouu|" +
|
"lanzouu|" +
|
||||||
"lanwp|" +
|
"lanwp|" +
|
||||||
"lanzouy|" +
|
"lanzouy|" +
|
||||||
"lanzoup|" +
|
"lanzoup|" +
|
||||||
"woozooo|" +
|
"woozooo|" +
|
||||||
"lanzv|" +
|
"lanzv|" +
|
||||||
"dmpdmp|" +
|
"dmpdmp|" +
|
||||||
"lanrar|" +
|
"lanrar|" +
|
||||||
"webgetstore|" +
|
"lanzb|" +
|
||||||
"lanzb|" +
|
"lanzoux|" +
|
||||||
"lanzoux|" +
|
"lanzout|" +
|
||||||
"lanzout|" +
|
"lanzouc|" +
|
||||||
"lanzouc|" +
|
"lanzoui|" +
|
||||||
"lanzoui|" +
|
"lanzoug|" +
|
||||||
"lanzoug|" +
|
"lanzoum" +
|
||||||
"lanzoum" +
|
")\\.com/(?<KEY>.+)"),
|
||||||
")\\.com/(.+/)?(?<KEY>.+)"),
|
|
||||||
"https://w1.lanzn.com/{shareKey}",
|
"https://w1.lanzn.com/{shareKey}",
|
||||||
LzTool.class),
|
LzTool.class),
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class LzTool extends PanBase {
|
|||||||
String html = asText(res);
|
String html = asText(res);
|
||||||
if (html.contains("var arg1='")) {
|
if (html.contains("var arg1='")) {
|
||||||
webClientSession = WebClientSession.create(clientNoRedirects);
|
webClientSession = WebClientSession.create(clientNoRedirects);
|
||||||
setCookie(html);
|
setCookie(html, sUrl);
|
||||||
webClientSession.getAbs(sUrl)
|
webClientSession.getAbs(sUrl)
|
||||||
.putHeaders(headers0)
|
.putHeaders(headers0)
|
||||||
.send().onSuccess(res2 -> {
|
.send().onSuccess(res2 -> {
|
||||||
@@ -81,6 +81,29 @@ public class LzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doParser(String html, String pwd, String sUrl) {
|
private void doParser(String html, String pwd, String sUrl) {
|
||||||
|
// 检测是否为目录分享链接 (含 /s/、/b/ 路径段或 b0 开头的路径段)
|
||||||
|
if (sUrl.matches(".*/(s|b)/[^/]+.*") || sUrl.matches(".*/b0[^/]+.*")) {
|
||||||
|
fail("该链接为蓝奏云目录分享,请使用目录解析接口");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 若仍是校验页 (parse()中cookie域名与实际URL不匹配时会出现), 重试一次
|
||||||
|
if (html.contains("var arg1='")) {
|
||||||
|
webClientSession = WebClientSession.create(clientNoRedirects);
|
||||||
|
setCookie(html, sUrl);
|
||||||
|
webClientSession.getAbs(sUrl).putHeaders(headers0).send().onSuccess(res -> {
|
||||||
|
String html2 = asText(res);
|
||||||
|
if (html2.contains("var arg1='")) {
|
||||||
|
fail("蓝奏云反爬校验失败,请稍后重试");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doParserInternal(html2, pwd, sUrl);
|
||||||
|
}).onFailure(handleFail(sUrl));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doParserInternal(html, pwd, sUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doParserInternal(String html, String pwd, String sUrl) {
|
||||||
try {
|
try {
|
||||||
setFileInfo(html, shareLinkInfo);
|
setFileInfo(html, shareLinkInfo);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -98,20 +121,18 @@ public class LzTool extends PanBase {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(e, "js引擎执行失败");
|
fail(e, "js引擎执行失败");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 没有密码
|
// 没有密码
|
||||||
String iframePath = matcher.group(1);
|
String iframePath = matcher.group(1);
|
||||||
String absoluteURI = SHARE_URL_PREFIX + iframePath;
|
String absoluteURI = SHARE_URL_PREFIX + iframePath;
|
||||||
webClientSession.getAbs(absoluteURI).putHeaders(headers0).send().onSuccess(res2 -> {
|
webClientSession.getAbs(absoluteURI).putHeaders(headers0).send().onSuccess(res2 -> {
|
||||||
String html2= asText(res2);
|
String html2 = asText(res2);
|
||||||
// Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'(\\w+)'").matcher(html2);
|
|
||||||
String jsText = getJsText(html2);
|
String jsText = getJsText(html2);
|
||||||
if (jsText == null) {
|
if (jsText == null) {
|
||||||
headers0.add("Referer", absoluteURI);
|
headers0.add("Referer", absoluteURI);
|
||||||
setCookie(html2);
|
setCookie(html2, absoluteURI);
|
||||||
webClientSession.getAbs(absoluteURI).send().onSuccess(res3 -> {
|
webClientSession.getAbs(absoluteURI).send().onSuccess(res3 -> {
|
||||||
String html3= asText(res3);
|
String html3 = asText(res3);
|
||||||
String jsText3 = getJsText(html3);
|
String jsText3 = getJsText(html3);
|
||||||
if (jsText3 != null) {
|
if (jsText3 != null) {
|
||||||
try {
|
try {
|
||||||
@@ -120,10 +141,8 @@ public class LzTool extends PanBase {
|
|||||||
} catch (ScriptException | NoSuchMethodException e) {
|
} catch (ScriptException | NoSuchMethodException e) {
|
||||||
fail(e, "引擎执行失败");
|
fail(e, "引擎执行失败");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
fail(SHARE_URL_PREFIX + iframePath + " -> " + sUrl + ": 获取失败0, 可能分享已失效");
|
fail(SHARE_URL_PREFIX + iframePath + " -> " + sUrl + ": 获取失败0, 可能分享已失效");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -138,14 +157,29 @@ public class LzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCookie(String html2) {
|
private void setCookie(String html, String url) {
|
||||||
int beginIndex = html2.indexOf("arg1='") + 6;
|
int beginIndex = html.indexOf("arg1='") + 6;
|
||||||
String arg1 = html2.substring(beginIndex, html2.indexOf("';", beginIndex));
|
int endIndex = html.indexOf("';", beginIndex);
|
||||||
|
if (beginIndex < 6 || endIndex == -1 || endIndex <= beginIndex) {
|
||||||
|
fail("蓝奏云反爬 arg1 Cookie 解析失败,页面内容异常");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String arg1 = html.substring(beginIndex, endIndex);
|
||||||
String acw_sc__v2 = AcwScV2Generator.acwScV2Simple(arg1);
|
String acw_sc__v2 = AcwScV2Generator.acwScV2Simple(arg1);
|
||||||
|
// 从 URL 中动态提取域名(如 lanzoum.com, lanzoux.com 等)
|
||||||
|
String domain = ".lanzn.com"; // 默认兜底
|
||||||
|
try {
|
||||||
|
java.net.URL urlObj = new java.net.URL(url);
|
||||||
|
String host = urlObj.getHost(); // e.g. "dzvip.lanzoum.com"
|
||||||
|
int firstDot = host.indexOf('.');
|
||||||
|
if (firstDot >= 0) {
|
||||||
|
domain = host.substring(firstDot); // e.g. ".lanzoum.com"
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
// 创建一个 Cookie 并放入 CookieStore
|
// 创建一个 Cookie 并放入 CookieStore
|
||||||
DefaultCookie nettyCookie = new DefaultCookie("acw_sc__v2", acw_sc__v2);
|
DefaultCookie nettyCookie = new DefaultCookie("acw_sc__v2", acw_sc__v2);
|
||||||
nettyCookie.setDomain(".lanzn.com"); // 设置域名
|
nettyCookie.setDomain(domain);
|
||||||
nettyCookie.setPath("/"); // 设置路径
|
nettyCookie.setPath("/");
|
||||||
nettyCookie.setSecure(false);
|
nettyCookie.setSecure(false);
|
||||||
nettyCookie.setHttpOnly(false);
|
nettyCookie.setHttpOnly(false);
|
||||||
webClientSession.cookieStore().put(nettyCookie);
|
webClientSession.cookieStore().put(nettyCookie);
|
||||||
@@ -234,10 +268,18 @@ public class LzTool extends PanBase {
|
|||||||
int beginIndex = text.indexOf("arg1='") + 6;
|
int beginIndex = text.indexOf("arg1='") + 6;
|
||||||
String arg1 = text.substring(beginIndex, text.indexOf("';", beginIndex));
|
String arg1 = text.substring(beginIndex, text.indexOf("';", beginIndex));
|
||||||
String acw_sc__v2 = AcwScV2Generator.acwScV2Simple(arg1);
|
String acw_sc__v2 = AcwScV2Generator.acwScV2Simple(arg1);
|
||||||
|
// 从 downUrl 中动态提取域名
|
||||||
|
String downDomain = ".lanrar.com";
|
||||||
|
try {
|
||||||
|
java.net.URL du = new java.net.URL(downUrl);
|
||||||
|
String h = du.getHost();
|
||||||
|
int dot = h.indexOf('.');
|
||||||
|
if (dot >= 0) downDomain = h.substring(dot);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
// 创建一个 Cookie 并放入 CookieStore
|
// 创建一个 Cookie 并放入 CookieStore
|
||||||
DefaultCookie nettyCookie = new DefaultCookie("acw_sc__v2", acw_sc__v2);
|
DefaultCookie nettyCookie = new DefaultCookie("acw_sc__v2", acw_sc__v2);
|
||||||
nettyCookie.setDomain(".lanrar.com"); // 设置域名
|
nettyCookie.setDomain(downDomain);
|
||||||
nettyCookie.setPath("/"); // 设置路径
|
nettyCookie.setPath("/");
|
||||||
nettyCookie.setSecure(false);
|
nettyCookie.setSecure(false);
|
||||||
nettyCookie.setHttpOnly(false);
|
nettyCookie.setHttpOnly(false);
|
||||||
WebClientSession webClientSession2 = WebClientSession.create(clientNoRedirects);
|
WebClientSession webClientSession2 = WebClientSession.create(clientNoRedirects);
|
||||||
@@ -295,14 +337,14 @@ public class LzTool extends PanBase {
|
|||||||
String pwd = shareLinkInfo.getSharePassword();
|
String pwd = shareLinkInfo.getSharePassword();
|
||||||
|
|
||||||
webClientSession.getAbs(sUrl).send().onSuccess(res -> {
|
webClientSession.getAbs(sUrl).send().onSuccess(res -> {
|
||||||
String html = res.bodyAsString();
|
String html = asText(res);
|
||||||
// 检查是否需要 cookie 验证
|
// 检查是否需要 cookie 验证
|
||||||
if (html.contains("var arg1='")) {
|
if (html.contains("var arg1='")) {
|
||||||
webClientSession = WebClientSession.create(clientNoRedirects);
|
webClientSession = WebClientSession.create(clientNoRedirects);
|
||||||
setCookie(html);
|
setCookie(html, sUrl);
|
||||||
// 重新请求
|
// 重新请求
|
||||||
webClientSession.getAbs(sUrl).send().onSuccess(res2 -> {
|
webClientSession.getAbs(sUrl).send().onSuccess(res2 -> {
|
||||||
handleFileListParse(res2.bodyAsString(), pwd, sUrl, promise);
|
handleFileListParse(asText(res2), pwd, sUrl, promise);
|
||||||
}).onFailure(err -> promise.fail(err));
|
}).onFailure(err -> promise.fail(err));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -312,6 +354,11 @@ public class LzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleFileListParse(String html, String pwd, String sUrl, Promise<List<FileInfo>> promise) {
|
private void handleFileListParse(String html, String pwd, String sUrl, Promise<List<FileInfo>> promise) {
|
||||||
|
// 检测是否为文件分享链接 (不含 /s/、/b/ 路径段且不含 b0 开头的路径段)
|
||||||
|
if (!sUrl.matches(".*/(s|b)/[^/]+.*") && !sUrl.matches(".*/b0[^/]+.*")) {
|
||||||
|
promise.fail(baseMsg() + "该链接为蓝奏云文件分享,请使用文件解析接口");
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
String jsText = getJsByPwd(pwd, html, "var urls =window.location.href");
|
String jsText = getJsByPwd(pwd, html, "var urls =window.location.href");
|
||||||
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, "file");
|
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, "file");
|
||||||
@@ -321,12 +368,12 @@ public class LzTool extends PanBase {
|
|||||||
log.debug("解析参数: {}", map);
|
log.debug("解析参数: {}", map);
|
||||||
MultiMap headers = getHeaders(sUrl);
|
MultiMap headers = getHeaders(sUrl);
|
||||||
|
|
||||||
String url = SHARE_URL_PREFIX + "/filemoreajax.php?file=" + data.get("fid");
|
String url = SHARE_URL_PREFIX + "filemoreajax.php?file=" + data.get("fid");
|
||||||
webClientSession.postAbs(url).putHeaders(headers).sendForm(map).onSuccess(res2 -> {
|
webClientSession.postAbs(url).putHeaders(headers).sendForm(map).onSuccess(res2 -> {
|
||||||
String resBody = asText(res2);
|
String resBody = asText(res2);
|
||||||
// 再次检查是否需要 cookie 验证
|
// 再次检查是否需要 cookie 验证
|
||||||
if (resBody.contains("var arg1='")) {
|
if (resBody.contains("var arg1='")) {
|
||||||
setCookie(resBody);
|
setCookie(resBody, url);
|
||||||
// 重新请求
|
// 重新请求
|
||||||
webClientSession.postAbs(url).putHeaders(headers).sendForm(map).onSuccess(res3 -> {
|
webClientSession.postAbs(url).putHeaders(headers).sendForm(map).onSuccess(res3 -> {
|
||||||
handleFileListResponse(asText(res3), promise);
|
handleFileListResponse(asText(res3), promise);
|
||||||
@@ -335,7 +382,7 @@ public class LzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
handleFileListResponse(resBody, promise);
|
handleFileListResponse(resBody, promise);
|
||||||
}).onFailure(err -> promise.fail(err));
|
}).onFailure(err -> promise.fail(err));
|
||||||
} catch (ScriptException | NoSuchMethodException e) {
|
} catch (ScriptException | NoSuchMethodException | RuntimeException e) {
|
||||||
promise.fail(e);
|
promise.fail(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,14 +414,20 @@ public class LzTool extends PanBase {
|
|||||||
Long sizeNum = FileSizeConverter.convertToBytes(size);
|
Long sizeNum = FileSizeConverter.convertToBytes(size);
|
||||||
String panType = shareLinkInfo.getType();
|
String panType = shareLinkInfo.getType();
|
||||||
String id = fileJson.getString("id");
|
String id = fileJson.getString("id");
|
||||||
fileInfo.setFileName(fileJson.getString("name_all"))
|
String fileName = fileJson.getString("name_all");
|
||||||
|
// 构建 base64 参数,用于 /v2/redirectUrl 接口
|
||||||
|
JsonObject paramJson = new JsonObject()
|
||||||
|
.put("id", id)
|
||||||
|
.put("fileName", fileName);
|
||||||
|
String param = CommonUtils.urlBase64Encode(paramJson.encode());
|
||||||
|
fileInfo.setFileName(fileName)
|
||||||
.setFileId(id)
|
.setFileId(id)
|
||||||
.setCreateTime(fileJson.getString("time"))
|
.setCreateTime(fileJson.getString("time"))
|
||||||
.setFileType(fileJson.getString("icon"))
|
.setFileType(fileJson.getString("icon"))
|
||||||
.setSizeStr(fileJson.getString("size"))
|
.setSizeStr(fileJson.getString("size"))
|
||||||
.setSize(sizeNum)
|
.setSize(sizeNum)
|
||||||
.setPanType(panType)
|
.setPanType(panType)
|
||||||
.setParserUrl(getDomainName() + "/d/" + panType + "/" + id)
|
.setParserUrl(String.format("%s/v2/redirectUrl/%s/%s", getDomainName(), panType, param))
|
||||||
.setPreviewUrl(String.format("%s/v2/view/%s/%s", getDomainName(),
|
.setPreviewUrl(String.format("%s/v2/view/%s/%s", getDomainName(),
|
||||||
shareLinkInfo.getType(), id));
|
shareLinkInfo.getType(), id));
|
||||||
log.debug("文件信息: {}", fileInfo);
|
log.debug("文件信息: {}", fileInfo);
|
||||||
@@ -386,6 +439,15 @@ public class LzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<String> parseById() {
|
||||||
|
JsonObject paramJson = (JsonObject) shareLinkInfo.getOtherParam().get("paramJson");
|
||||||
|
String id = paramJson.getString("id");
|
||||||
|
// 以文件ID重新构造标准访问URL,复用 parse() 流程
|
||||||
|
shareLinkInfo.setStandardUrl(SHARE_URL_PREFIX + id);
|
||||||
|
return parse();
|
||||||
|
}
|
||||||
|
|
||||||
void setFileInfo(String html, ShareLinkInfo shareLinkInfo) {
|
void setFileInfo(String html, ShareLinkInfo shareLinkInfo) {
|
||||||
// 写入 fileInfo
|
// 写入 fileInfo
|
||||||
FileInfo fileInfo = new FileInfo();
|
FileInfo fileInfo = new FileInfo();
|
||||||
@@ -400,16 +462,17 @@ public class LzTool extends PanBase {
|
|||||||
String fileId = CommonUtils.extract(html, Pattern.compile("\\?f=(.*?)&|fid = (.*?);"));
|
String fileId = CommonUtils.extract(html, Pattern.compile("\\?f=(.*?)&|fid = (.*?);"));
|
||||||
String createTime = CommonUtils.extract(html, Pattern.compile(">上传时间:</span>(.*?)<"));
|
String createTime = CommonUtils.extract(html, Pattern.compile(">上传时间:</span>(.*?)<"));
|
||||||
try {
|
try {
|
||||||
long bytes = FileSizeConverter.convertToBytes(sizeStr);
|
|
||||||
fileInfo.setFileName(fileName)
|
fileInfo.setFileName(fileName)
|
||||||
.setSize(bytes)
|
|
||||||
.setSizeStr(FileSizeConverter.convertToReadableSize(bytes))
|
|
||||||
.setCreateBy(createBy)
|
.setCreateBy(createBy)
|
||||||
.setPanType(shareLinkInfo.getType())
|
.setPanType(shareLinkInfo.getType())
|
||||||
.setDescription(description)
|
.setDescription(description)
|
||||||
.setFileType("file")
|
.setFileType("file")
|
||||||
.setFileId(fileId)
|
.setFileId(fileId)
|
||||||
.setCreateTime(createTime);
|
.setCreateTime(createTime);
|
||||||
|
if (sizeStr != null && !sizeStr.isBlank()) {
|
||||||
|
long bytes = FileSizeConverter.convertToBytes(sizeStr);
|
||||||
|
fileInfo.setSize(bytes).setSizeStr(FileSizeConverter.convertToReadableSize(bytes));
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("文件信息解析异常", e);
|
log.warn("文件信息解析异常", e);
|
||||||
}
|
}
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -74,7 +74,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.qaiu</groupId>
|
<groupId>cn.qaiu</groupId>
|
||||||
<artifactId>parser</artifactId>
|
<artifactId>parser</artifactId>
|
||||||
<version>10.2.3</version>
|
<version>10.2.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|||||||
Reference in New Issue
Block a user