|
|
|
|
@ -2,16 +2,7 @@ package com.github.catvod.spider; |
|
|
|
|
|
|
|
|
|
import android.app.AlertDialog; |
|
|
|
|
import android.content.Context; |
|
|
|
|
import android.content.DialogInterface; |
|
|
|
|
import android.content.Intent; |
|
|
|
|
import android.graphics.Color; |
|
|
|
|
import android.graphics.drawable.ColorDrawable; |
|
|
|
|
import android.net.Uri; |
|
|
|
|
import android.text.TextUtils; |
|
|
|
|
import android.util.Base64; |
|
|
|
|
import android.view.Gravity; |
|
|
|
|
import android.widget.FrameLayout; |
|
|
|
|
import android.widget.ImageView; |
|
|
|
|
|
|
|
|
|
import com.github.catvod.bean.Class; |
|
|
|
|
import com.github.catvod.bean.Filter; |
|
|
|
|
@ -25,15 +16,14 @@ import com.github.catvod.bean.bili.Resp; |
|
|
|
|
import com.github.catvod.crawler.Spider; |
|
|
|
|
import com.github.catvod.net.OkHttp; |
|
|
|
|
import com.github.catvod.utils.FileUtil; |
|
|
|
|
import com.github.catvod.utils.QRCode; |
|
|
|
|
import com.github.catvod.utils.Utils; |
|
|
|
|
import com.google.gson.JsonArray; |
|
|
|
|
import com.google.gson.JsonObject; |
|
|
|
|
import com.google.gson.JsonParser; |
|
|
|
|
|
|
|
|
|
import org.json.JSONArray; |
|
|
|
|
import org.json.JSONObject; |
|
|
|
|
|
|
|
|
|
import java.io.ByteArrayInputStream; |
|
|
|
|
import java.io.File; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.net.URLEncoder; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
@ -42,40 +32,30 @@ import java.util.LinkedHashMap; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Locale; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.concurrent.Executors; |
|
|
|
|
import java.util.concurrent.ScheduledExecutorService; |
|
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author ColaMint & FongMi & 唐三 |
|
|
|
|
*/ |
|
|
|
|
public class Bili extends Spider { |
|
|
|
|
|
|
|
|
|
private static final String COOKIE = "buvid3=84B0395D-C9F2-C490-E92E-A09AB48FE26E71636infoc"; |
|
|
|
|
private static Map<String, String> audios; |
|
|
|
|
private static String cookie; |
|
|
|
|
|
|
|
|
|
private ScheduledExecutorService service; |
|
|
|
|
private Map<String, String> audios; |
|
|
|
|
private AlertDialog dialog; |
|
|
|
|
private JsonObject extend; |
|
|
|
|
private String cookie; |
|
|
|
|
private boolean login; |
|
|
|
|
private boolean ask; |
|
|
|
|
private boolean isVip; |
|
|
|
|
|
|
|
|
|
private Map<String, String> getHeader(String cookie) { |
|
|
|
|
private static Map<String, String> getHeader() { |
|
|
|
|
Map<String, String> headers = new HashMap<>(); |
|
|
|
|
headers.put("cookie", cookie); |
|
|
|
|
headers.put("User-Agent", Utils.CHROME); |
|
|
|
|
if (cookie != null) headers.put("cookie", cookie); |
|
|
|
|
headers.put("Referer", "https://www.bilibili.com"); |
|
|
|
|
return headers; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Map<String, String> getGuest() { |
|
|
|
|
return getHeader(COOKIE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Map<String, String> getMember() { |
|
|
|
|
return getHeader(cookie); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void setAudio() { |
|
|
|
|
audios = new HashMap<>(); |
|
|
|
|
audios.put("30280", "192000"); |
|
|
|
|
@ -83,11 +63,18 @@ public class Bili extends Spider { |
|
|
|
|
audios.put("30216", "64000"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void setCookie() { |
|
|
|
|
private String getCookie() throws IOException { |
|
|
|
|
List<String> cookies = OkHttp.newCall("https://www.bilibili.com", getHeader()).headers("set-cookie"); |
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
for (String cookie : cookies) sb.append(cookie.split(";")[0]).append(";"); |
|
|
|
|
return sb.toString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void setCookie() throws IOException { |
|
|
|
|
cookie = extend.get("cookie").getAsString(); |
|
|
|
|
if (cookie.startsWith("http")) cookie = OkHttp.string(cookie).trim(); |
|
|
|
|
if (TextUtils.isEmpty(cookie)) cookie = FileUtil.read(getUserCache()); |
|
|
|
|
if (TextUtils.isEmpty(cookie)) cookie = COOKIE; |
|
|
|
|
if (TextUtils.isEmpty(cookie)) cookie = getCookie(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private List<Filter> getFilter() { |
|
|
|
|
@ -102,7 +89,7 @@ public class Bili extends Spider { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void init(Context context, String extend) { |
|
|
|
|
public void init(Context context, String extend) throws Exception { |
|
|
|
|
this.extend = JsonParser.parseString(extend).getAsJsonObject(); |
|
|
|
|
setCookie(); |
|
|
|
|
setAudio(); |
|
|
|
|
@ -124,7 +111,7 @@ public class Bili extends Spider { |
|
|
|
|
@Override |
|
|
|
|
public String homeVideoContent() { |
|
|
|
|
String api = "https://api.bilibili.com/x/web-interface/popular?ps=20"; |
|
|
|
|
String json = OkHttp.string(api, getGuest()); |
|
|
|
|
String json = OkHttp.string(api, getHeader()); |
|
|
|
|
Resp resp = Resp.objectFrom(json); |
|
|
|
|
List<Vod> list = new ArrayList<>(); |
|
|
|
|
for (Resp.Result item : Resp.Result.arrayFrom(resp.getData().getList())) list.add(item.getVod()); |
|
|
|
|
@ -137,7 +124,7 @@ public class Bili extends Spider { |
|
|
|
|
String duration = extend.containsKey("duration") ? extend.get("duration") : "0"; |
|
|
|
|
if (extend.containsKey("tid")) tid = tid + " " + extend.get("tid"); |
|
|
|
|
String api = "https://api.bilibili.com/x/web-interface/search/type?search_type=video&keyword=" + URLEncoder.encode(tid) + "&order=" + order + "&duration=" + duration + "&page=" + pg; |
|
|
|
|
String json = OkHttp.string(api, getGuest()); |
|
|
|
|
String json = OkHttp.string(api, getHeader()); |
|
|
|
|
Resp resp = Resp.objectFrom(json); |
|
|
|
|
List<Vod> list = new ArrayList<>(); |
|
|
|
|
for (Resp.Result item : Resp.Result.arrayFrom(resp.getData().getResult())) list.add(item.getVod()); |
|
|
|
|
@ -146,14 +133,14 @@ public class Bili extends Spider { |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String detailContent(List<String> ids) throws Exception { |
|
|
|
|
if (!login && !ask) checkLogin(); |
|
|
|
|
if (!login) checkLogin(); |
|
|
|
|
|
|
|
|
|
String[] split = ids.get(0).split("@"); |
|
|
|
|
String bvid = split[0]; |
|
|
|
|
String aid = split[1]; |
|
|
|
|
|
|
|
|
|
String api = "https://api.bilibili.com/x/web-interface/view?aid=" + aid; |
|
|
|
|
String json = OkHttp.string(api, getMember()); |
|
|
|
|
String json = OkHttp.string(api, getHeader()); |
|
|
|
|
Data detail = Resp.objectFrom(json).getData(); |
|
|
|
|
Vod vod = new Vod(); |
|
|
|
|
vod.setVodId(ids.get(0)); |
|
|
|
|
@ -163,19 +150,33 @@ public class Bili extends Spider { |
|
|
|
|
vod.setVodContent(detail.getDesc()); |
|
|
|
|
vod.setVodRemarks(detail.getDuration() / 60 + "分鐘"); |
|
|
|
|
|
|
|
|
|
List<String> acceptDesc = new ArrayList<>(); |
|
|
|
|
List<Integer> acceptQuality = new ArrayList<>(); |
|
|
|
|
api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + detail.getCid() + "&qn=127&fnval=4048&fourk=1"; |
|
|
|
|
json = OkHttp.string(api, getHeader()); |
|
|
|
|
Data play = Resp.objectFrom(json).getData(); |
|
|
|
|
for (int i = 0; i < play.getAcceptQuality().size(); i++) { |
|
|
|
|
int qn = play.getAcceptQuality().get(i); |
|
|
|
|
if (!login && qn > 32) continue; |
|
|
|
|
if (!isVip && qn > 80) continue; |
|
|
|
|
acceptQuality.add(play.getAcceptQuality().get(i)); |
|
|
|
|
acceptDesc.add(play.getAcceptDescription().get(i)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<String> episode = new ArrayList<>(); |
|
|
|
|
LinkedHashMap<String, String> flag = new LinkedHashMap<>(); |
|
|
|
|
ArrayList<String> episode = new ArrayList<>(); |
|
|
|
|
for (Page page : detail.getPages()) episode.add(page.getPart() + "$" + aid + "+" + page.getCid()); |
|
|
|
|
for (Page page : detail.getPages()) episode.add(page.getPart() + "$" + aid + "+" + page.getCid() + "+" + TextUtils.join(":", acceptQuality) + "+" + TextUtils.join(":", acceptDesc)); |
|
|
|
|
flag.put("B站", TextUtils.join("#", episode)); |
|
|
|
|
|
|
|
|
|
episode = new ArrayList<>(); |
|
|
|
|
api = "https://api.bilibili.com/x/web-interface/archive/related?bvid=" + bvid; |
|
|
|
|
JSONArray array = new JSONObject(OkHttp.string(api, getMember())).optJSONArray("data"); |
|
|
|
|
for (int i = 0; i < array.length(); i++) { |
|
|
|
|
JSONObject object = array.getJSONObject(i); |
|
|
|
|
episode.add(object.getString("title") + "$" + object.optLong("aid") + "+" + object.optLong("cid")); |
|
|
|
|
json = OkHttp.string(api, getHeader()); |
|
|
|
|
JsonArray array = JsonParser.parseString(json).getAsJsonObject().getAsJsonArray("data"); |
|
|
|
|
for (int i = 0; i < array.size(); i++) { |
|
|
|
|
JsonObject object = array.get(i).getAsJsonObject(); |
|
|
|
|
episode.add(object.get("title").getAsString() + "$" + object.get("aid").getAsInt() + "+" + object.get("cid").getAsInt() + "+" + TextUtils.join(":", acceptQuality) + "+" + TextUtils.join(":", acceptDesc)); |
|
|
|
|
} |
|
|
|
|
flag.put("相关推荐", TextUtils.join("#", episode)); |
|
|
|
|
flag.put("相关", TextUtils.join("#", episode)); |
|
|
|
|
|
|
|
|
|
vod.setVodPlayFrom(TextUtils.join("$$$", flag.keySet())); |
|
|
|
|
vod.setVodPlayUrl(TextUtils.join("$$$", flag.values())); |
|
|
|
|
@ -197,27 +198,38 @@ public class Bili extends Spider { |
|
|
|
|
String[] ids = id.split("\\+"); |
|
|
|
|
String aid = ids[0]; |
|
|
|
|
String cid = ids[1]; |
|
|
|
|
String qn = "127"; |
|
|
|
|
String[] acceptDesc = ids[3].split(":"); |
|
|
|
|
String[] acceptQuality = ids[2].split(":"); |
|
|
|
|
List<String> url = new ArrayList<>(); |
|
|
|
|
String dan = "https://api.bilibili.com/x/v1/dm/list.so?oid=".concat(cid); |
|
|
|
|
for (int i = 0; i < acceptDesc.length; i++) { |
|
|
|
|
url.add(acceptDesc[i]); |
|
|
|
|
url.add(Proxy.getUrl() + "?do=bili" + "&aid=" + aid + "&cid=" + cid + "&qn=" + acceptQuality[i]); |
|
|
|
|
} |
|
|
|
|
return Result.get().url(url).danmaku(dan).dash().header(getHeader()).string(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Object[] proxy(Map<String, String> params) { |
|
|
|
|
String aid = params.get("aid"); |
|
|
|
|
String cid = params.get("cid"); |
|
|
|
|
String qn = params.get("qn"); |
|
|
|
|
String api = "https://api.bilibili.com/x/player/playurl?avid=" + aid + "&cid=" + cid + "&qn=" + qn + "&fnval=4048&fourk=1"; |
|
|
|
|
String json = OkHttp.string(api, getMember()); |
|
|
|
|
String json = OkHttp.string(api, getHeader()); |
|
|
|
|
Resp resp = Resp.objectFrom(json); |
|
|
|
|
Dash dash = resp.getData().getDash(); |
|
|
|
|
|
|
|
|
|
StringBuilder video = new StringBuilder(); |
|
|
|
|
StringBuilder audio = new StringBuilder(); |
|
|
|
|
findAudio(dash, audio); |
|
|
|
|
findVideo(dash, video, qn); |
|
|
|
|
boolean empty = video.length() == 0 && dash.getVideo().size() > 0; |
|
|
|
|
if (empty) findVideo(dash, video, dash.getVideo().get(0).getId()); |
|
|
|
|
|
|
|
|
|
String mpd = getMpd(dash, video.toString(), audio.toString()); |
|
|
|
|
String dan = "https://api.bilibili.com/x/v1/dm/list.so?oid=".concat(cid); |
|
|
|
|
String url = "data:application/dash+xml;base64," + Base64.encodeToString(mpd.getBytes(), 0); |
|
|
|
|
return Result.get().url(url).danmaku(dan).dash().header(getMember()).string(); |
|
|
|
|
Object[] result = new Object[3]; |
|
|
|
|
result[0] = 200; |
|
|
|
|
result[1] = "application/dash+xml"; |
|
|
|
|
result[2] = new ByteArrayInputStream(mpd.getBytes()); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void findAudio(Dash dash, StringBuilder sb) { |
|
|
|
|
private static void findAudio(Dash dash, StringBuilder sb) { |
|
|
|
|
for (Media audio : dash.getAudio()) { |
|
|
|
|
for (String key : audios.keySet()) { |
|
|
|
|
if (audio.getId().equals(key)) { |
|
|
|
|
@ -227,7 +239,7 @@ public class Bili extends Spider { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void findVideo(Dash dash, StringBuilder sb, String qn) { |
|
|
|
|
private static void findVideo(Dash dash, StringBuilder sb, String qn) { |
|
|
|
|
for (Media video : dash.getVideo()) { |
|
|
|
|
if (video.getId().equals(qn)) { |
|
|
|
|
sb.append(getMedia(video)); |
|
|
|
|
@ -235,7 +247,7 @@ public class Bili extends Spider { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String getMedia(Media media) { |
|
|
|
|
private static String getMedia(Media media) { |
|
|
|
|
if (media.getMimeType().startsWith("video")) { |
|
|
|
|
return getAdaptationSet(media, String.format(Locale.getDefault(), "height='%s' width='%s' frameRate='%s' sar='%s'", media.getHeight(), media.getWidth(), media.getFrameRate(), media.getSar())); |
|
|
|
|
} else if (media.getMimeType().startsWith("audio")) { |
|
|
|
|
@ -245,27 +257,28 @@ public class Bili extends Spider { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String getAdaptationSet(Media media, String params) { |
|
|
|
|
private static String getAdaptationSet(Media media, String params) { |
|
|
|
|
String id = media.getId() + "_" + media.getCodecId(); |
|
|
|
|
String type = media.getMimeType().split("/")[0]; |
|
|
|
|
String baseUrl = media.getBaseUrl().replace("&", "&"); |
|
|
|
|
return String.format(Locale.getDefault(), "<AdaptationSet>\n" + "<ContentComponent contentType=\"%s\"/>\n" + "<Representation id=\"%s\" bandwidth=\"%s\" codecs=\"%s\" mimeType=\"%s\" %s startWithSAP=\"%s\">\n" + "<BaseURL>%s</BaseURL>\n" + "<SegmentBase indexRange=\"%s\">\n" + "<Initialization range=\"%s\"/>\n" + "</SegmentBase>\n" + "</Representation>\n" + "</AdaptationSet>", type, 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) { |
|
|
|
|
private static String getMpd(Dash dash, String videoList, String audioList) { |
|
|
|
|
return String.format(Locale.getDefault(), "<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" + "<Period duration=\"PT%sS\" start=\"PT0S\">\n" + "%s\n" + "%s\n" + "</Period>\n" + "</MPD>", dash.getDuration(), dash.getMinBufferTime(), dash.getDuration(), videoList, audioList); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void checkLogin() { |
|
|
|
|
String json = OkHttp.string("https://api.bilibili.com/x/web-interface/nav", getMember()); |
|
|
|
|
String json = OkHttp.string("https://api.bilibili.com/x/web-interface/nav", getHeader()); |
|
|
|
|
Data data = Resp.objectFrom(json).getData(); |
|
|
|
|
isVip = data.getVipStatus(); |
|
|
|
|
login = data.isLogin(); |
|
|
|
|
getQRCode(); |
|
|
|
|
//getQRCode();
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
private void getQRCode() { |
|
|
|
|
if (login) return; |
|
|
|
|
ask = true; |
|
|
|
|
String json = OkHttp.string("https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-mini"); |
|
|
|
|
Data data = Resp.objectFrom(json).getData(); |
|
|
|
|
Init.run(() -> openApp(data)); |
|
|
|
|
@ -308,7 +321,7 @@ public class Bili extends Spider { |
|
|
|
|
service = Executors.newScheduledThreadPool(1); |
|
|
|
|
service.scheduleAtFixedRate(() -> { |
|
|
|
|
String url = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + data.getQrcodeKey() + "&source=main_mini"; |
|
|
|
|
String json = OkHttp.string(url, getGuest()); |
|
|
|
|
String json = OkHttp.string(url, getHeader()); |
|
|
|
|
url = Resp.objectFrom(json).getData().getUrl(); |
|
|
|
|
if (url.length() > 0) setCookie(url); |
|
|
|
|
}, 1, 1, TimeUnit.SECONDS); |
|
|
|
|
@ -329,7 +342,7 @@ public class Bili extends Spider { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void cancel(DialogInterface dialog) { |
|
|
|
|
FileUtil.write(getUserCache(), cookie = COOKIE); |
|
|
|
|
FileUtil.write(getUserCache(), cookie = ""); |
|
|
|
|
stopService(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -343,4 +356,5 @@ public class Bili extends Spider { |
|
|
|
|
} catch (Exception ignored) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
|