1 Star 2 Fork 1

summer cat001/homer-service

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
CC2VideoResolver.java 6.30 KB
一键复制 编辑 原始数据 按行查看 历史
caojiancheng 提交于 2024-07-16 14:50 . 增加破解反爬虫策略
package com.microcosm.homer.service.impl;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.microcosm.homer.model.HttpRespBO;
import com.microcosm.homer.model.video.NetVideoBO;
import com.microcosm.homer.model.video.SearchItemBO;
import com.microcosm.homer.model.video.SearchSourceItemBO;
import com.microcosm.homer.service.CommonVideoResolver;
import com.microcosm.homer.utils.AESUtil;
import com.microcosm.homer.utils.Assert;
import com.microcosm.homer.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author summer
* @date 2023-12-01 11:48
* 星辰影院/策驰影院
*/
@Slf4j
@Service("cc2VideoResolver")
public class CC2VideoResolver extends CommonVideoResolver {
private static final Pattern m3u8UrlPat = Pattern.compile("\"url\":\"(.*?)\"");
private static final Pattern m3u8NamePat = Pattern.compile("<title>(.*?)</title>");
private static final Pattern encKeyPat = Pattern.compile("#EXT-X-KEY:METHOD=(.*?),.*?IV=(.*?)\n");
private static final Pattern searchPat = Pattern.compile("<a class=\"img-pic\"[\\s\\S]*?href=\"(.*?)\"[\\s\\S]*?title=\"(.*?)\"[\\s\\S]*?data-original=\"(.*?)\"");
private static final Pattern videoSourcePat = Pattern.compile("<a href=\"javascript:void[\\s\\S]*?id=\"#(.*?)\"[\\s\\S]*?>(.*?)</a>");
private static final Pattern videoLiPat = Pattern.compile("[^']<li[\\s\\S]*?href=\"(.*?)\">(.*?)</a>");
public CC2VideoResolver() {
super("http://www.zjzqxc.com", "星辰影院2");
}
//guardok Cookie的Max-Age=21600,所以本地缓存6小时;
private final LoadingCache<Integer, Map<String, String>> headCache = Caffeine.newBuilder()
.maximumSize(1).expireAfterWrite(6, TimeUnit.HOURS).build(this::antiAntiCrawler);
@Override
public Map<String, String> getDefaultHeaderMap() {
//突破反爬虫策略
return headCache.get(0);
}
@Override
public boolean support(String url) {
return url != null && url.contains("zjzqxc.com");
}
@Override
public UnaryOperator<byte[]> getDecodeTsFunction(String head, byte[] encKey) {
Matcher encKeyMatcher = encKeyPat.matcher(head);
if (encKeyMatcher.find()) {
String method = encKeyMatcher.group(1);
return method.contains("aes") || method.contains("AES") ? encByte -> AESUtil.decode(encByte, encKey, "0000000000000000") : null;
}
return null;
}
@Override
protected Pattern getM3U8UrlPat() {
return m3u8UrlPat;
}
@Override
protected Pattern getM3U8NamePat() {
return m3u8NamePat;
}
@Override
protected String resolveSearchContent(String content) {
return content;
}
@Override
protected List<SearchItemBO> resolveSearchItemList(String searchContent) {
return resolveSearchItemListTemplate(searchContent, searchPat, matcher -> matcher.group(1), matcher -> matcher.group(2), matcher -> matcher.group(3), UnaryOperator.identity());
}
@Override
protected List<SearchSourceItemBO> resolveNetVideoSource(String searchItemPage) {
return resolvePlayListNetVideoSource(searchItemPage, videoSourcePat, matcher -> matcher.group(2), matcher -> matcher.group(1));
}
@Override
protected List<NetVideoBO> resolveNetVideo(String sourceContent) {
return resolveNetVideoTemplate(sourceContent, videoLiPat, matcher -> matcher.group(1), matcher -> matcher.group(2));
}
private Map<String, String> antiAntiCrawler(int param) {
//获取guard
String url = "http://www.zjzqxc.com/video/40004.html";
HttpRespBO httpRespBO = HttpUtil.httpGet(url);
Assert.isTrue(httpRespBO, "获取guard失败", () ->
log.error("CC2VideoResolver getDefaultHeaderMap fail respBO:{}", httpRespBO));
Map<String, List<String>> headerMap = httpRespBO.getHeaderMap();
List<String> setCookie = headerMap.get("Set-Cookie");
Assert.isNotEmpty(setCookie, "CC2VideoResolver 获取guard失败 Set-Cookie 不存在");
String guard = Arrays.stream(setCookie.get(0).split(";"))
.filter(c -> c.startsWith("guard=")).findFirst().orElse(null);
Assert.isNotEmpty(guard, "CC2VideoResolver guard不存在 ");
//生成guardRet
String guardRet = getGuardRet(guard.replace("guard=", ""));
//换取访问凭证guardok
Map<String, String> okHeaderMap = new HashMap<>();
okHeaderMap.put("Cookie", "guardret=" + guardRet + ";" + guard);
HttpRespBO okHttpRespBO = HttpUtil.httpGet(url, okHeaderMap);
Assert.isNotEmpty(okHttpRespBO, "获取guard ok失败");
Map<String, List<String>> okResHeaderMap = okHttpRespBO.getHeaderMap();
List<String> okSetCookie = okResHeaderMap.get("Set-Cookie");
Assert.isNotEmpty(okSetCookie, "CC2VideoResolver 获取guard ok失败 Set-Cookie 不存在");
String guardOk = Arrays.stream(okSetCookie.get(0).split(";"))
.filter(c -> c.startsWith("guardok=")).findFirst().orElse(null);
Assert.isNotEmpty(guardOk, "CC2VideoResolver guard ok不存在 ");
//返回请求头
//注意:这个guardOk要搭配者ua一起用,如果后续ua传的和生成guardOk的ua不一致的话也不会通过验签的
Map<String, String> defaultHeaderMap = new HashMap<>();
defaultHeaderMap.put("Cookie", guardOk);
return defaultHeaderMap;
}
private String x(String a, String b) {
b = b + "PTNo2n3Ev5";
StringBuilder output = new StringBuilder();
for (int i = 0; i < a.length(); i++) {
int charCode = Character.codePointAt(a, i) ^ Character.codePointAt(b, i % b.length());
output.append((char) charCode);
}
return output.toString();
}
private String getGuardRet(String guard) {
String b = guard.substring(0, 8);
int aInt = Integer.parseInt(guard.substring(12));
String a = ((aInt * 0x2) + 0x12 - 0x2) + "";
String encrypted = x(a, b);
Base64.Encoder encoder = Base64.getEncoder();
return new String(encoder.encode(encrypted.getBytes()));
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/summer-cat001/homer-service.git
git@gitee.com:summer-cat001/homer-service.git
summer-cat001
homer-service
homer-service
master

搜索帮助

A270a887 8829481 3d7a4017 8829481