Merge branch 'main' of https://github.com/FongMi/CatVodSpider
This commit is contained in:
commit
4e6807cffc
|
|
@ -44,6 +44,5 @@ dependencies {
|
||||||
implementation 'com.google.code.gson:gson:2.8.6'
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
implementation 'cn.wanghaomiao:JsoupXpath:2.5.1'
|
implementation 'cn.wanghaomiao:JsoupXpath:2.5.1'
|
||||||
implementation 'com.google.zxing:core:3.3.0'
|
implementation 'com.google.zxing:core:3.3.0'
|
||||||
//implementation 'com.orhanobut:logger:2.2.0'
|
|
||||||
implementation 'org.jsoup:jsoup:1.15.3'
|
implementation 'org.jsoup:jsoup:1.15.3'
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ public class Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class(String typeId, String typeName) {
|
public Class(String typeId, String typeName) {
|
||||||
this(typeId, typeName, "");
|
this(typeId, typeName, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class(String typeId, String typeName, String typeFlag) {
|
public Class(String typeId, String typeName, String typeFlag) {
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,13 @@ public class Result {
|
||||||
@SerializedName("jx")
|
@SerializedName("jx")
|
||||||
private int jx;
|
private int jx;
|
||||||
@SerializedName("page")
|
@SerializedName("page")
|
||||||
private int page;
|
private Integer page;
|
||||||
@SerializedName("pagecount")
|
@SerializedName("pagecount")
|
||||||
private int pagecount;
|
private Integer pagecount;
|
||||||
@SerializedName("limit")
|
@SerializedName("limit")
|
||||||
private int limit;
|
private Integer limit;
|
||||||
@SerializedName("total")
|
@SerializedName("total")
|
||||||
private int total;
|
private Integer total;
|
||||||
|
|
||||||
public static Result objectFrom(String str) {
|
public static Result objectFrom(String str) {
|
||||||
return new Gson().fromJson(str, Result.class);
|
return new Gson().fromJson(str, Result.class);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Dash {
|
||||||
|
|
||||||
|
@SerializedName("duration")
|
||||||
|
private String duration;
|
||||||
|
@SerializedName("minBufferTime")
|
||||||
|
private String minBufferTime;
|
||||||
|
@SerializedName("video")
|
||||||
|
private List<Media> video;
|
||||||
|
@SerializedName("audio")
|
||||||
|
private List<Media> audio;
|
||||||
|
|
||||||
|
public static Dash objectFrom(String str) {
|
||||||
|
return new Gson().fromJson(str, Dash.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDuration() {
|
||||||
|
return duration == null ? "0" : duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMinBufferTime() {
|
||||||
|
return minBufferTime == null ? "0" : minBufferTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Media> getVideo() {
|
||||||
|
return video == null ? Collections.emptyList() : video;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Media> getAudio() {
|
||||||
|
return audio == null ? Collections.emptyList() : audio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Data {
|
||||||
|
|
||||||
|
@SerializedName("result")
|
||||||
|
private JsonElement result;
|
||||||
|
@SerializedName("isLogin")
|
||||||
|
private Boolean isLogin;
|
||||||
|
@SerializedName("vipType")
|
||||||
|
private Integer vipType;
|
||||||
|
@SerializedName("qrcode_key")
|
||||||
|
private String qrcodeKey;
|
||||||
|
@SerializedName("url")
|
||||||
|
private String url;
|
||||||
|
@SerializedName("aid")
|
||||||
|
private String aid;
|
||||||
|
@SerializedName("cid")
|
||||||
|
private String cid;
|
||||||
|
@SerializedName("title")
|
||||||
|
private String title;
|
||||||
|
@SerializedName("tname")
|
||||||
|
private String tname;
|
||||||
|
@SerializedName("pic")
|
||||||
|
private String pic;
|
||||||
|
@SerializedName("duration")
|
||||||
|
private Long duration;
|
||||||
|
@SerializedName("desc")
|
||||||
|
private String desc;
|
||||||
|
@SerializedName("accept_description")
|
||||||
|
private List<String> acceptDescription;
|
||||||
|
@SerializedName("accept_quality")
|
||||||
|
private List<Integer> acceptQuality;
|
||||||
|
@SerializedName("pages")
|
||||||
|
private List<Page> pages;
|
||||||
|
@SerializedName("dash")
|
||||||
|
private Dash dash;
|
||||||
|
|
||||||
|
public JsonElement getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLogin() {
|
||||||
|
return isLogin != null && isLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVipType() {
|
||||||
|
return vipType == null ? 0 : vipType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQrcodeKey() {
|
||||||
|
return TextUtils.isEmpty(qrcodeKey) ? "" : qrcodeKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return TextUtils.isEmpty(url) ? "" : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAid() {
|
||||||
|
return TextUtils.isEmpty(aid) ? "" : aid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCid() {
|
||||||
|
return TextUtils.isEmpty(cid) ? "" : cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return TextUtils.isEmpty(title) ? "" : title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return TextUtils.isEmpty(tname) ? "" : tname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPic() {
|
||||||
|
return TextUtils.isEmpty(pic) ? "" : pic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDuration() {
|
||||||
|
return duration == null ? 0 : duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return TextUtils.isEmpty(desc) ? "" : desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAcceptDescription() {
|
||||||
|
return acceptDescription == null ? Collections.emptyList() : acceptDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getAcceptQuality() {
|
||||||
|
return acceptQuality == null ? Collections.emptyList() : acceptQuality;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Page> getPages() {
|
||||||
|
return pages == null ? Collections.emptyList() : pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dash getDash() {
|
||||||
|
return dash == null ? new Dash() : dash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class Media {
|
||||||
|
|
||||||
|
@SerializedName("id")
|
||||||
|
private String id;
|
||||||
|
@SerializedName("baseUrl")
|
||||||
|
private String baseUrl;
|
||||||
|
@SerializedName("bandwidth")
|
||||||
|
private String bandwidth;
|
||||||
|
@SerializedName("mimeType")
|
||||||
|
private String mimeType;
|
||||||
|
@SerializedName("codecs")
|
||||||
|
private String codecs;
|
||||||
|
@SerializedName("width")
|
||||||
|
private String width;
|
||||||
|
@SerializedName("height")
|
||||||
|
private String height;
|
||||||
|
@SerializedName("frameRate")
|
||||||
|
private String frameRate;
|
||||||
|
@SerializedName("sar")
|
||||||
|
private String sar;
|
||||||
|
@SerializedName("startWithSap")
|
||||||
|
private String startWithSap;
|
||||||
|
@SerializedName("SegmentBase")
|
||||||
|
private Segment segmentBase;
|
||||||
|
@SerializedName("codecid")
|
||||||
|
private String codecid;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBandWidth() {
|
||||||
|
return bandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCodecs() {
|
||||||
|
return codecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrameRate() {
|
||||||
|
return frameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSar() {
|
||||||
|
return sar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartWithSap() {
|
||||||
|
return startWithSap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Segment getSegmentBase() {
|
||||||
|
return segmentBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCodecId() {
|
||||||
|
return codecid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class Page {
|
||||||
|
|
||||||
|
@SerializedName("cid")
|
||||||
|
private String cid;
|
||||||
|
@SerializedName("part")
|
||||||
|
private String part;
|
||||||
|
|
||||||
|
public String getCid() {
|
||||||
|
return TextUtils.isEmpty(cid) ? "" : cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPart() {
|
||||||
|
return TextUtils.isEmpty(part) ? "" : part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.github.catvod.bean.Vod;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Resp {
|
||||||
|
|
||||||
|
@SerializedName("code")
|
||||||
|
private Integer code;
|
||||||
|
@SerializedName("message")
|
||||||
|
private String message;
|
||||||
|
@SerializedName("data")
|
||||||
|
private Data data;
|
||||||
|
|
||||||
|
public static Resp objectFrom(String str) {
|
||||||
|
return new Gson().fromJson(str, Resp.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data getData() {
|
||||||
|
return data == null ? new Data() : data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Result {
|
||||||
|
|
||||||
|
@SerializedName("bvid")
|
||||||
|
private String bvid;
|
||||||
|
@SerializedName("title")
|
||||||
|
private String title;
|
||||||
|
@SerializedName("pic")
|
||||||
|
private String pic;
|
||||||
|
@SerializedName("duration")
|
||||||
|
private String duration;
|
||||||
|
|
||||||
|
public static List<Result> arrayFrom(JsonElement str) {
|
||||||
|
Type listType = new TypeToken<List<Result>>() {}.getType();
|
||||||
|
return new Gson().fromJson(str, listType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBvId() {
|
||||||
|
return TextUtils.isEmpty(bvid) ? "" : bvid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return TextUtils.isEmpty(title) ? "" : title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDuration() {
|
||||||
|
return TextUtils.isEmpty(duration) ? "" : duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPic() {
|
||||||
|
return TextUtils.isEmpty(pic) ? "" : pic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vod getVod() {
|
||||||
|
Vod vod = new Vod();
|
||||||
|
vod.setVodId(getBvId());
|
||||||
|
vod.setVodName(Jsoup.parse(getTitle()).text());
|
||||||
|
vod.setVodRemarks(getDuration().split(":")[0] + "分鐘");
|
||||||
|
vod.setVodPic(getPic().startsWith("//") ? "https:" + getPic() : getPic());
|
||||||
|
return vod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.github.catvod.bean.bili;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class Segment {
|
||||||
|
|
||||||
|
@SerializedName("Initialization")
|
||||||
|
private String initialization;
|
||||||
|
@SerializedName("indexRange")
|
||||||
|
private String indexRange;
|
||||||
|
|
||||||
|
public String getInitialization() {
|
||||||
|
return initialization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIndexRange() {
|
||||||
|
return indexRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,11 @@ public class MainActivity extends Activity {
|
||||||
//Logger.addLogAdapter(new AndroidLogAdapter());
|
//Logger.addLogAdapter(new AndroidLogAdapter());
|
||||||
Init.init(getApplicationContext());
|
Init.init(getApplicationContext());
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,22 +13,29 @@ import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.github.catvod.bean.Class;
|
import com.github.catvod.bean.Class;
|
||||||
|
import com.github.catvod.bean.Filter;
|
||||||
import com.github.catvod.bean.Result;
|
import com.github.catvod.bean.Result;
|
||||||
import com.github.catvod.bean.Vod;
|
import com.github.catvod.bean.Vod;
|
||||||
|
import com.github.catvod.bean.bili.Dash;
|
||||||
|
import com.github.catvod.bean.bili.Data;
|
||||||
|
import com.github.catvod.bean.bili.Media;
|
||||||
|
import com.github.catvod.bean.bili.Page;
|
||||||
|
import com.github.catvod.bean.bili.Resp;
|
||||||
import com.github.catvod.crawler.Spider;
|
import com.github.catvod.crawler.Spider;
|
||||||
import com.github.catvod.net.OkHttp;
|
import com.github.catvod.net.OkHttp;
|
||||||
import com.github.catvod.utils.Prefers;
|
import com.github.catvod.utils.FileUtil;
|
||||||
import com.github.catvod.utils.QRCode;
|
import com.github.catvod.utils.QRCode;
|
||||||
import com.github.catvod.utils.Utils;
|
import com.github.catvod.utils.Utils;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import java.io.File;
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
@ -38,57 +45,51 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
public class Bili extends Spider {
|
public class Bili extends Spider {
|
||||||
|
|
||||||
|
private static final String COOKIE = "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc";
|
||||||
private ScheduledExecutorService service;
|
private ScheduledExecutorService service;
|
||||||
private HashMap<String, String> header;
|
private Map<String, String> header;
|
||||||
|
private Map<String, String> audios;
|
||||||
private AlertDialog dialog;
|
private AlertDialog dialog;
|
||||||
private JSONObject ext;
|
|
||||||
private String extend;
|
private String extend;
|
||||||
private boolean login;
|
private boolean login;
|
||||||
|
private boolean vip;
|
||||||
private String getCookie() {
|
|
||||||
String cache = Prefers.getString("BiliCookie");
|
|
||||||
if (!TextUtils.isEmpty(cache)) return cache;
|
|
||||||
if (ext.optString("cookie").startsWith("http"))
|
|
||||||
return OkHttp.string(ext.optString("cookie")).replace("\n", "").trim();
|
|
||||||
return ext.optString("cookie", "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setHeader() {
|
private void setHeader() {
|
||||||
|
header = new HashMap<>();
|
||||||
header.put("cookie", getCookie());
|
header.put("cookie", getCookie());
|
||||||
header.put("Referer", "https://www.bilibili.com");
|
|
||||||
header.put("User-Agent", Utils.CHROME);
|
header.put("User-Agent", Utils.CHROME);
|
||||||
|
header.put("Referer", "https://www.bilibili.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generate() throws Exception {
|
private void setAudio() {
|
||||||
ext = new JSONObject();
|
audios = new HashMap<>();
|
||||||
JSONArray classes = new JSONArray();
|
audios.put("30280", "192000");
|
||||||
JSONObject filters = new JSONObject();
|
audios.put("30232", "132000");
|
||||||
ext.put("classes", classes);
|
audios.put("30216", "64000");
|
||||||
ext.put("filter", filters);
|
|
||||||
JSONArray filter = new JSONArray("[{\"key\":\"order\",\"name\":\"排序\",\"value\":[{\"n\":\"综合排序\",\"v\":\"0\"},{\"n\":\"最多点击\",\"v\":\"click\"},{\"n\":\"最新发布\",\"v\":\"pubdate\"},{\"n\":\"最多弹幕\",\"v\":\"dm\"},{\"n\":\"最多收藏\",\"v\":\"stow\"}]},{\"key\":\"duration\",\"name\":\"时长\",\"value\":[{\"n\":\"全部时长\",\"v\":\"0\"},{\"n\":\"60分钟以上\",\"v\":\"4\"},{\"n\":\"30~60分钟\",\"v\":\"3\"},{\"n\":\"10~30分钟\",\"v\":\"2\"},{\"n\":\"10分钟以下\",\"v\":\"1\"}]}]");
|
|
||||||
String[] types = extend.split("#");
|
|
||||||
for (String type : types) {
|
|
||||||
JSONObject c = new JSONObject();
|
|
||||||
c.put("type_name", type);
|
|
||||||
c.put("type_id", type);
|
|
||||||
filters.put(type, filter);
|
|
||||||
classes.put(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchRule() throws Exception {
|
private List<Filter> getFilter() {
|
||||||
if (header.containsKey("cookie") && header.get("cookie").length() > 0) return;
|
List<Filter> items = new ArrayList<>();
|
||||||
if (extend.startsWith("http")) ext = new JSONObject(extend = OkHttp.string(extend));
|
items.add(new Filter("order", "排序", Arrays.asList(new Filter.Value("預設", "totalrank"), new Filter.Value("最多點擊", "click"), new Filter.Value("最新發布", "pubdate"), new Filter.Value("最多彈幕", "dm"), new Filter.Value("最多收藏", "stow"))));
|
||||||
else generate();
|
items.add(new Filter("duration", "時長", Arrays.asList(new Filter.Value("全部時長", "0"), new Filter.Value("60分鐘以上", "4"), new Filter.Value("30~60分鐘", "3"), new Filter.Value("10~30分鐘", "2"), new Filter.Value("10分鐘以下", "1"))));
|
||||||
setHeader();
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getUserCache() {
|
||||||
|
return FileUtil.getCacheFile("bilibili_user");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCookie() {
|
||||||
|
String cookie = FileUtil.read(getUserCache());
|
||||||
|
return TextUtils.isEmpty(cookie) ? COOKIE : cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Context context, String extend) {
|
public void init(Context context, String extend) {
|
||||||
try {
|
try {
|
||||||
this.extend = extend;
|
this.extend = extend;
|
||||||
this.header = new HashMap<>();
|
setHeader();
|
||||||
fetchRule();
|
setAudio();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
@ -96,63 +97,71 @@ public class Bili extends Spider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String homeContent(boolean filter) throws Exception {
|
public String homeContent(boolean filter) throws Exception {
|
||||||
fetchRule();
|
List<Class> classes = new ArrayList<>();
|
||||||
return Result.string(Class.arrayFrom(ext.getJSONArray("classes").toString()), ext.getJSONObject("filter"));
|
LinkedHashMap<String, List<Filter>> filters = new LinkedHashMap<>();
|
||||||
|
String[] types = extend.split("#");
|
||||||
|
for (String type : types) {
|
||||||
|
classes.add(new Class(type));
|
||||||
|
filters.put(type, getFilter());
|
||||||
|
}
|
||||||
|
return Result.string(classes, filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String homeVideoContent() throws Exception {
|
public String homeVideoContent() throws Exception {
|
||||||
fetchRule();
|
return categoryContent(extend.split("#")[0], "1", true, new HashMap<>());
|
||||||
return categoryContent(ext.optJSONArray("classes").optJSONObject(0).optString("type_id"), "1", true, new HashMap<>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
|
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) throws Exception {
|
||||||
String duration = extend.containsKey("duration") ? extend.get("duration") : "4";
|
String order = extend.containsKey("order") ? extend.get("order") : "totalrank";
|
||||||
if (extend.containsKey("tid")) tid = tid + " " + extend.get("tid");
|
String duration = extend.containsKey("duration") ? extend.get("duration") : "0";
|
||||||
String url = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(tid) + "&duration=" + duration + "&page=" + pg;
|
String api = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(tid) + "&order=" + order + "&duration=" + duration + "&page=" + pg;
|
||||||
JSONObject resp = new JSONObject(OkHttp.string(url, header));
|
String json = OkHttp.string(api, header);
|
||||||
JSONArray result = resp.getJSONObject("data").getJSONArray("result");
|
Resp resp = Resp.objectFrom(json);
|
||||||
List<Vod> list = new ArrayList<>();
|
List<Vod> list = new ArrayList<>();
|
||||||
for (int i = 0; i < result.length(); ++i) {
|
for (Resp.Result item : Resp.Result.arrayFrom(resp.getData().getResult())) list.add(item.getVod());
|
||||||
JSONObject object = result.getJSONObject(i);
|
|
||||||
String pic = object.getString("pic");
|
|
||||||
Vod vod = new Vod();
|
|
||||||
vod.setVodId(object.getString("bvid"));
|
|
||||||
vod.setVodName(Jsoup.parse(object.getString("title")).text());
|
|
||||||
vod.setVodRemarks(object.getString("duration").split(":")[0] + "分鐘");
|
|
||||||
vod.setVodPic(pic.startsWith("//") ? "https:" + pic : pic);
|
|
||||||
list.add(vod);
|
|
||||||
}
|
|
||||||
return Result.string(list);
|
return Result.string(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String detailContent(List<String> ids) throws Exception {
|
public String detailContent(List<String> ids) throws Exception {
|
||||||
if (!login) checkLogin();
|
if (!login) checkLogin();
|
||||||
String bvid = ids.get(0);
|
|
||||||
String bvid2aidUrl = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + bvid;
|
String id = ids.get(0);
|
||||||
JSONObject bvid2aidResp = new JSONObject(OkHttp.string(bvid2aidUrl, header));
|
String api = "https://api.bilibili.com/x/web-interface/archive/stat?bvid=" + id;
|
||||||
String aid = bvid2aidResp.getJSONObject("data").getLong("aid") + "";
|
String json = OkHttp.string(api, header);
|
||||||
String detailUrl = "https://api.bilibili.com/x/web-interface/view?aid=" + aid;
|
Resp resp = Resp.objectFrom(json);
|
||||||
JSONObject detailResp = new JSONObject(OkHttp.string(detailUrl, header));
|
String aid = resp.getData().getAid();
|
||||||
JSONObject detailData = detailResp.getJSONObject("data");
|
|
||||||
List<String> playlist = new ArrayList<>();
|
api = "https://api.bilibili.com/x/web-interface/view?aid=" + aid;
|
||||||
JSONArray pages = detailData.getJSONArray("pages");
|
json = OkHttp.string(api, header);
|
||||||
for (int i = 0; i < pages.length(); ++i) {
|
Data detail = Resp.objectFrom(json).getData();
|
||||||
JSONObject page = pages.getJSONObject(i);
|
|
||||||
String title = page.getString("part").replace("$", "_").replace("#", "_");
|
|
||||||
playlist.add(title + "$" + aid + "+" + page.getLong("cid"));
|
|
||||||
}
|
|
||||||
Vod vod = new Vod();
|
Vod vod = new Vod();
|
||||||
vod.setVodId(bvid);
|
vod.setVodId(id);
|
||||||
vod.setVodName(detailData.getString("title"));
|
vod.setVodPic(detail.getPic());
|
||||||
vod.setVodPic(detailData.getString("pic"));
|
vod.setVodName(detail.getTitle());
|
||||||
vod.setTypeName(detailData.getString("tname"));
|
vod.setTypeName(detail.getType());
|
||||||
vod.setVodRemarks(detailData.getLong("duration") / 60 + "分鐘");
|
vod.setVodContent(detail.getDesc());
|
||||||
vod.setVodContent(detailData.getString("desc"));
|
vod.setVodRemarks(detail.getDuration() / 60 + "分鐘");
|
||||||
vod.setVodPlayFrom("B站");
|
|
||||||
vod.setVodPlayUrl(TextUtils.join("#", playlist));
|
api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + detail.getCid() + "&qn=127&fnval=4048&fourk=1";
|
||||||
|
json = OkHttp.string(api, header);
|
||||||
|
Data play = Resp.objectFrom(json).getData();
|
||||||
|
List<String> playList = new ArrayList<>();
|
||||||
|
List<String> playFrom = new ArrayList<>();
|
||||||
|
for (int i = 0; i < play.getAcceptQuality().size(); i++) {
|
||||||
|
int quality = play.getAcceptQuality().get(i);
|
||||||
|
List<String> vodItems = new ArrayList<>();
|
||||||
|
if (!login && quality > 32) continue;
|
||||||
|
if (!vip && quality > 80) continue;
|
||||||
|
for (Page page : detail.getPages()) vodItems.add(page.getPart() + "$" + aid + "+" + page.getCid() + "+" + quality);
|
||||||
|
playList.add(TextUtils.join("#", vodItems));
|
||||||
|
playFrom.add(play.getAcceptDescription().get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vod.setVodPlayFrom(TextUtils.join("$$$", playFrom));
|
||||||
|
vod.setVodPlayUrl(TextUtils.join("$$$", playList));
|
||||||
return Result.string(vod);
|
return Result.string(vod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,135 +175,124 @@ public class Bili extends Spider {
|
||||||
String[] ids = id.split("\\+");
|
String[] ids = id.split("\\+");
|
||||||
String aid = ids[0];
|
String aid = ids[0];
|
||||||
String cid = ids[1];
|
String cid = ids[1];
|
||||||
String url = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + cid + "&qn=120&fnval=4048&fourk=1";
|
String qn = ids[2];
|
||||||
JSONObject resp = new JSONObject(OkHttp.string(url, header));
|
|
||||||
JSONObject dash = resp.optJSONObject("data").optJSONObject("dash");
|
String api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + cid + "&qn=" + qn + "&fnval=4048&fourk=1";
|
||||||
JSONArray video = dash.optJSONArray("video");
|
String json = OkHttp.string(api, header);
|
||||||
JSONArray audio = dash.optJSONArray("audio");
|
Resp resp = Resp.objectFrom(json);
|
||||||
|
Dash dash = resp.getData().getDash();
|
||||||
|
|
||||||
StringBuilder videoList = new StringBuilder();
|
StringBuilder videoList = new StringBuilder();
|
||||||
StringBuilder audioList = new StringBuilder();
|
StringBuilder audioList = new StringBuilder();
|
||||||
for (int i = 0; i < video.length(); i++) {
|
for (Media video : dash.getVideo()) {
|
||||||
JSONObject vjson = video.getJSONObject(i);
|
if (video.getId().equals(qn)) {
|
||||||
videoList.append(getDashMedia(vjson));
|
videoList.append(getMedia(video));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < audio.length(); i++) {
|
for (Media audio : dash.getAudio()) {
|
||||||
JSONObject ajson = audio.getJSONObject(i);
|
for (String key : audios.keySet()) {
|
||||||
audioList.append(getDashMedia(ajson));
|
if (audio.getId().equals(key)) {
|
||||||
|
audioList.append(getMedia(audio));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
String mpd = getDash(dash, videoList.toString(), audioList.toString());
|
|
||||||
String dashUrl = "data:application/dash+xml;base64," + Base64.encodeToString(mpd.getBytes(), 0);
|
String mpd = getMpd(dash, videoList.toString(), audioList.toString());
|
||||||
return Result.get().url(dashUrl).header(header).string();
|
String url = "data:application/dash+xml;base64," + Base64.encodeToString(mpd.getBytes(), 0);
|
||||||
|
return Result.get().url(url).header(header).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDashMedia(JSONObject dash) throws Exception {
|
private String getMedia(Media media) {
|
||||||
JSONObject vod_audio_id = new JSONObject();
|
if (media.getMimeType().startsWith("video")) {
|
||||||
vod_audio_id.put("30280", "192000");
|
return getAdaptationSet(media, String.format(Locale.getDefault(), "height='%s' width='%s' frameRate='%s' sar='%s'", media.getHeight(), media.getWidth(), media.getFrameRate(), media.getSar()));
|
||||||
vod_audio_id.put("30232", "132000");
|
} else if (media.getMimeType().startsWith("audio")) {
|
||||||
vod_audio_id.put("30216", "64000");
|
return getAdaptationSet(media, String.format("numChannels='2' sampleRate='%s'", audios.get(media.getId())));
|
||||||
String qnid = dash.getString("id");
|
} else {
|
||||||
int codecid = dash.getInt("codecid");
|
return "";
|
||||||
String media_codecs = dash.getString("codecs");
|
|
||||||
Integer media_bandwidth = dash.getInt("bandwidth");
|
|
||||||
String media_startWithSAP = dash.getString("startWithSap");
|
|
||||||
String media_mimeType = dash.getString("mimeType");
|
|
||||||
String media_BaseURL = dash.getString("baseUrl").replace("&", "&");
|
|
||||||
String media_SegmentBase_indexRange = dash.getJSONObject("SegmentBase").getString("indexRange");
|
|
||||||
String media_SegmentBase_Initialization = dash.getJSONObject("SegmentBase").getString("Initialization");
|
|
||||||
String mediaType = media_mimeType.split("/")[0];
|
|
||||||
String media_type_params = "";
|
|
||||||
|
|
||||||
if (mediaType.equals("video")) {
|
|
||||||
Integer media_frameRate = dash.getInt("frameRate");
|
|
||||||
String media_sar = dash.getString("sar");
|
|
||||||
Integer media_width = dash.getInt("width");
|
|
||||||
Integer media_height = dash.getInt("height");
|
|
||||||
media_type_params = String.format("height='%d' width='%d' frameRate='%d' sar='%s'", media_height, media_width, media_frameRate, media_sar);
|
|
||||||
} else if (mediaType.equals("audio")) {
|
|
||||||
String audioSamplingRate = vod_audio_id.getString(qnid);
|
|
||||||
media_type_params = String.format("numChannels='2' sampleRate='%s'", audioSamplingRate);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qnid += "_" + codecid;
|
private String getAdaptationSet(Media media, String params) {
|
||||||
|
String id = media.getId() + "_" + media.getCodecId();
|
||||||
return String.format(
|
String type = media.getMimeType().split("/")[0];
|
||||||
|
String baseUrl = media.getBaseUrl().replace("&", "&");
|
||||||
|
return String.format(Locale.getDefault(),
|
||||||
"<AdaptationSet>\n" +
|
"<AdaptationSet>\n" +
|
||||||
" <ContentComponent contentType=\"%s\"/>\n" +
|
"<ContentComponent contentType=\"%s\"/>\n" +
|
||||||
" <Representation id=\"%s\" bandwidth=\"%d\" codecs=\"%s\" mimeType=\"%s\" %s startWithSAP=\"%b\">\n" +
|
"<Representation id=\"%s\" bandwidth=\"%s\" codecs=\"%s\" mimeType=\"%s\" %s startWithSAP=\"%s\">\n" +
|
||||||
" <BaseURL>%s</BaseURL>\n" +
|
"<BaseURL>%s</BaseURL>\n" +
|
||||||
" <SegmentBase indexRange=\"%s\">\n" +
|
"<SegmentBase indexRange=\"%s\">\n" +
|
||||||
" <Initialization range=\"%s\"/>\n" +
|
"<Initialization range=\"%s\"/>\n" +
|
||||||
" </SegmentBase>\n" +
|
"</SegmentBase>\n" +
|
||||||
" </Representation>\n" +
|
"</Representation>\n" +
|
||||||
" </AdaptationSet>",
|
"</AdaptationSet>",
|
||||||
mediaType, qnid, media_bandwidth, media_codecs, media_mimeType, media_type_params, media_startWithSAP, media_BaseURL,
|
type,
|
||||||
media_SegmentBase_indexRange, media_SegmentBase_Initialization);
|
id, media.getBandWidth(), media.getCodecs(), media.getMimeType(), params, media.getStartWithSap(),
|
||||||
|
baseUrl,
|
||||||
|
media.getSegmentBase().getIndexRange(),
|
||||||
|
media.getSegmentBase().getInitialization());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getMpd(Dash dash, String videoList, String audioList) {
|
||||||
public static String getDash(JSONObject ja, String videoList, String audioList) throws Exception {
|
return String.format(Locale.getDefault(),
|
||||||
Integer duration = ja.getInt("duration");
|
"<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:mpeg:dash:schema:mpd:2011\" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" type=\"static\" mediaPresentationDuration=\"PT%sS\" minBufferTime=\"PT%sS\" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\">\n" +
|
||||||
Integer minBufferTime = ja.getInt("minBufferTime");
|
"<Period duration=\"PT%sS\" start=\"PT0S\">\n" +
|
||||||
return String.format(
|
"%s\n" +
|
||||||
"<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"urn:mpeg:dash:schema:mpd:2011\" xsi:schemaLocation=\"urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd\" type=\"static\" mediaPresentationDuration=\"PT%dS\" minBufferTime=\"PT%dS\" profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\">\n" +
|
"%s\n" +
|
||||||
" <Period duration=\"PT%dS\" start=\"PT0S\">\n" +
|
"</Period>\n" +
|
||||||
" %s\n" +
|
|
||||||
" %s\n" +
|
|
||||||
" </Period>\n" +
|
|
||||||
"</MPD>",
|
"</MPD>",
|
||||||
duration, minBufferTime, duration, videoList, audioList);
|
dash.getDuration(), dash.getMinBufferTime(),
|
||||||
|
dash.getDuration(),
|
||||||
|
videoList,
|
||||||
|
audioList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkLogin() throws Exception {
|
private void checkLogin() {
|
||||||
login = new JSONObject(OkHttp.string("https://api.bilibili.com/x/web-interface/nav", header)).getJSONObject("data").getBoolean("isLogin");
|
String json = OkHttp.string("https://api.bilibili.com/x/web-interface/nav", header);
|
||||||
boolean qrCode = Prefers.getBoolean("BiliQRCode", true);
|
Data data = Resp.objectFrom(json).getData();
|
||||||
if (!login && qrCode) getQRCode();
|
login = data.isLogin();
|
||||||
|
vip = data.getVipType() > 0;
|
||||||
|
if (!login && !getUserCache().exists()) getQRCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getQRCode() {
|
private void getQRCode() {
|
||||||
try {
|
String json = OkHttp.string("https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-mini");
|
||||||
String json = OkHttp.string("https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-mini", null);
|
Data data = Resp.objectFrom(json).getData();
|
||||||
JSONObject data = new JSONObject(json).getJSONObject("data");
|
Init.run(() -> showQRCode(data));
|
||||||
Init.run(() -> showQRCode(data));
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showQRCode(JSONObject data) {
|
private void showQRCode(Data data) {
|
||||||
try {
|
try {
|
||||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Utils.dp2px(240), Utils.dp2px(240));
|
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(Utils.dp2px(240), Utils.dp2px(240));
|
||||||
ImageView image = new ImageView(Init.context());
|
ImageView image = new ImageView(Init.context());
|
||||||
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||||
image.setImageBitmap(QRCode.getBitmap(data.getString("url"), 240, 2));
|
image.setImageBitmap(QRCode.getBitmap(data.getUrl(), 240, 2));
|
||||||
FrameLayout frame = new FrameLayout(Init.context());
|
FrameLayout frame = new FrameLayout(Init.context());
|
||||||
params.gravity = Gravity.CENTER;
|
params.gravity = Gravity.CENTER;
|
||||||
frame.addView(image, params);
|
frame.addView(image, params);
|
||||||
dialog = new AlertDialog.Builder(Init.getActivity()).setView(frame).setOnDismissListener(this::dismiss).show();
|
dialog = new AlertDialog.Builder(Init.getActivity()).setView(frame).setOnDismissListener(this::dismiss).show();
|
||||||
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
Init.execute(() -> startService(data));
|
|
||||||
Init.show("請使用 BiliBili App 掃描二維碼");
|
Init.show("請使用 BiliBili App 掃描二維碼");
|
||||||
|
Init.execute(() -> startService(data));
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startService(JSONObject data) {
|
private void startService(Data data) {
|
||||||
service = Executors.newScheduledThreadPool(1);
|
service = Executors.newScheduledThreadPool(1);
|
||||||
service.scheduleAtFixedRate(() -> {
|
service.scheduleAtFixedRate(() -> {
|
||||||
try {
|
String url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + data.getQrcodeKey() + "&source=main_mini";
|
||||||
String qr = data.getString("qrcode_key");
|
String json = OkHttp.string(url, header);
|
||||||
String url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qr + "&source=main_mini";
|
url = Resp.objectFrom(json).getData().getUrl();
|
||||||
String json = OkHttp.string(url, header);
|
if (url.length() > 0) setCookie(url);
|
||||||
url = new JSONObject(json).getJSONObject("data").getString("url");
|
|
||||||
if (!TextUtils.isEmpty(url)) setCookie(url);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}, 1, 1, TimeUnit.SECONDS);
|
}, 1, 1, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCookie(String url) {
|
private void setCookie(String url) {
|
||||||
StringBuilder cookie = new StringBuilder();
|
StringBuilder cookie = new StringBuilder();
|
||||||
String[] aa = Uri.parse(url).getQuery().split("&");
|
String[] splits = Uri.parse(url).getQuery().split("&");
|
||||||
for (String a : aa) cookie.append(a).append(";");
|
for (String split : splits) cookie.append(split).append(";");
|
||||||
Prefers.put("BiliCookie", cookie.toString());
|
FileUtil.write(getUserCache(), cookie.toString());
|
||||||
Init.show("請重新進入播放頁");
|
Init.show("請重新進入播放頁");
|
||||||
stopService();
|
stopService();
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +303,7 @@ public class Bili extends Spider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dismiss(DialogInterface dialog) {
|
private void dismiss(DialogInterface dialog) {
|
||||||
Prefers.put("BiliQRCode", false);
|
FileUtil.write(getUserCache(), COOKIE);
|
||||||
stopService();
|
stopService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,4 +313,4 @@ public class Bili extends Spider {
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
b7931872492dbe98f688172bb9382a25
|
cc4a1d56205fd4d1039b53ba3175b81f
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;b7931872492dbe98f688172bb9382a25",
|
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;cc4a1d56205fd4d1039b53ba3175b81f",
|
||||||
"wallpaper": "https://gao.chuqiuyu.tk",
|
"wallpaper": "https://gao.chuqiuyu.tk",
|
||||||
"sites": [
|
"sites": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"cookie": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/txt/cookie.txt",
|
|
||||||
"classes": [
|
|
||||||
{
|
|
||||||
"type_name": "帕梅拉",
|
|
||||||
"type_id": "帕梅拉"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "太极拳",
|
|
||||||
"type_id": "太极拳"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "广场舞",
|
|
||||||
"type_id": "广场舞"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "健身",
|
|
||||||
"type_id": "健身"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "舞蹈",
|
|
||||||
"type_id": "舞蹈"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "电影",
|
|
||||||
"type_id": "电影"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "电视剧",
|
|
||||||
"type_id": "电视剧"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "演唱会",
|
|
||||||
"type_id": "演唱会"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type_name": "动物世界",
|
|
||||||
"type_id": "动物世界"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filter": {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;b7931872492dbe98f688172bb9382a25",
|
"spider": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/jar/custom_spider.jar;md5;cc4a1d56205fd4d1039b53ba3175b81f",
|
||||||
"wallpaper": "http://饭太硬.top/深色壁纸/api.php",
|
"wallpaper": "http://饭太硬.top/深色壁纸/api.php",
|
||||||
"sites": [
|
"sites": [
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
"api": "csp_Bili",
|
"api": "csp_Bili",
|
||||||
"searchable": 1,
|
"searchable": 1,
|
||||||
"changeable": 0,
|
"changeable": 0,
|
||||||
"ext": "https://raw.githubusercontent.com/FongMi/CatVodSpider/main/json/bili.json"
|
"ext": "帕梅拉#太极拳#广场舞#演唱会"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "泥巴",
|
"key": "泥巴",
|
||||||
|
|
@ -280,6 +280,16 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rules": [
|
"rules": [
|
||||||
|
{
|
||||||
|
"name": "星星",
|
||||||
|
"hosts": [
|
||||||
|
"aws.ulivetv.net"
|
||||||
|
],
|
||||||
|
"regex": [
|
||||||
|
"#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:8,[\\s\\S]*?#EXT-X-DISCONTINUITY",
|
||||||
|
"#EXT-X-DISCONTINUITY\\r*\\n*#EXTINF:9,[\\s\\S]*?#EXT-X-DISCONTINUITY"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "量子廣告",
|
"name": "量子廣告",
|
||||||
"hosts": [
|
"hosts": [
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue