Initial project - part 2
This commit is contained in:
parent
81e4e9d0ee
commit
c9c5acf060
|
|
@ -0,0 +1,40 @@
|
|||
package com.github.catvod.crawler;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Spider {
|
||||
|
||||
public void init(Context context) {
|
||||
}
|
||||
|
||||
public void init(Context context, String extend) {
|
||||
init(context);
|
||||
}
|
||||
|
||||
public String homeContent(boolean filter) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String homeVideoContent() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String categoryContent(String tid, String pg, boolean filter, HashMap<String, String> extend) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String detailContent(List<String> ids) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String searchContent(String key, boolean quick) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String playerContent(String flag, String id, List<String> vipFlags) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.github.catvod.crawler;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class SpiderDebug {
|
||||
|
||||
private static final String TAG = SpiderDebug.class.getSimpleName();
|
||||
|
||||
public static void log(Throwable th) {
|
||||
Log.d(TAG, th.getMessage());
|
||||
}
|
||||
|
||||
public static void log(String msg) {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package com.github.catvod.live;
|
||||
|
||||
import com.github.catvod.net.OkHttpUtil;
|
||||
import com.github.catvod.utils.Trans;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class TxtSubscribe {
|
||||
|
||||
public static void subscribe(LinkedHashMap<String, LinkedHashMap<String, ArrayList<String>>> allLives, String url, HashMap<String, String> headers) {
|
||||
String content = OkHttpUtil.string(url, headers);
|
||||
parse(allLives, content);
|
||||
}
|
||||
|
||||
public static void parse(LinkedHashMap<String, LinkedHashMap<String, ArrayList<String>>> allLives, String txt) {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new StringReader(txt));
|
||||
String line = br.readLine();
|
||||
LinkedHashMap<String, ArrayList<String>> noGroup = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, ArrayList<String>> groupLives = noGroup;
|
||||
while (line != null) {
|
||||
if (line.trim().isEmpty()) {
|
||||
line = br.readLine();
|
||||
continue;
|
||||
}
|
||||
String[] lineInfo = line.split(",");
|
||||
if (lineInfo.length < 2) {
|
||||
line = br.readLine();
|
||||
continue;
|
||||
}
|
||||
if (line.contains("#genre#")) {
|
||||
String group = Trans.get(lineInfo[0].trim());
|
||||
if (!allLives.containsKey(group)) {
|
||||
groupLives = new LinkedHashMap<>();
|
||||
allLives.put(group, groupLives);
|
||||
} else {
|
||||
groupLives = allLives.get(group);
|
||||
}
|
||||
} else {
|
||||
String title = Trans.get(lineInfo[0].trim());
|
||||
String[] urlMix = lineInfo[1].trim().split("#");
|
||||
for (String mix : urlMix) {
|
||||
String url = mix.trim();
|
||||
if (url.isEmpty()) continue;
|
||||
if (url.startsWith("http") || url.startsWith("rtsp") || url.startsWith("rtmp")) {
|
||||
ArrayList<String> urls;
|
||||
if (!groupLives.containsKey(title)) {
|
||||
urls = new ArrayList<>();
|
||||
groupLives.put(title, urls);
|
||||
} else {
|
||||
urls = groupLives.get(title);
|
||||
}
|
||||
if (!urls.contains(url)) urls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
line = br.readLine();
|
||||
}
|
||||
br.close();
|
||||
if (!noGroup.isEmpty()) {
|
||||
allLives.put("未分類", noGroup);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static String live2Json(LinkedHashMap<String, LinkedHashMap<String, ArrayList<String>>> lives) {
|
||||
JSONArray groups = new JSONArray();
|
||||
for (String group : lives.keySet()) {
|
||||
JSONArray channels = new JSONArray();
|
||||
LinkedHashMap<String, ArrayList<String>> allChannel = lives.get(group);
|
||||
if (allChannel.isEmpty()) continue;
|
||||
for (String channel : allChannel.keySet()) {
|
||||
ArrayList<String> allUrls = allChannel.get(channel);
|
||||
if (allUrls.isEmpty()) continue;
|
||||
JSONArray urls = new JSONArray();
|
||||
for (int i = 0; i < allUrls.size(); i++) {
|
||||
urls.put(allUrls.get(i));
|
||||
}
|
||||
JSONObject newChannel = new JSONObject();
|
||||
try {
|
||||
newChannel.put("name", channel);
|
||||
newChannel.put("urls", urls);
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
channels.put(newChannel);
|
||||
}
|
||||
JSONObject newGroup = new JSONObject();
|
||||
try {
|
||||
newGroup.put("group", group);
|
||||
newGroup.put("channels", channels);
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
groups.put(newGroup);
|
||||
}
|
||||
return groups.toString();
|
||||
}
|
||||
|
||||
public static Object[] load(String ext) {
|
||||
try {
|
||||
LinkedHashMap<String, LinkedHashMap<String, ArrayList<String>>> allLives = new LinkedHashMap<>();
|
||||
TxtSubscribe.subscribe(allLives, ext, null);
|
||||
String json = TxtSubscribe.live2Json(allLives);
|
||||
Object[] result = new Object[3];
|
||||
result[0] = 200;
|
||||
result[1] = "text/plain; charset=utf-8";
|
||||
ByteArrayInputStream baos = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
|
||||
result[2] = baos;
|
||||
return result;
|
||||
} catch (Throwable th) {
|
||||
th.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package com.github.catvod.net;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Response;
|
||||
|
||||
public abstract class OKCallBack<T> {
|
||||
|
||||
private T result = null;
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void setResult(T val) {
|
||||
result = val;
|
||||
}
|
||||
|
||||
protected void onError(final Call call, final Exception e) {
|
||||
onFailure(call, e);
|
||||
}
|
||||
|
||||
protected void onSuccess(Call call, Response response) {
|
||||
T obj = onParseResponse(call, response);
|
||||
setResult(obj);
|
||||
onResponse(obj);
|
||||
}
|
||||
|
||||
protected abstract T onParseResponse(Call call, Response response);
|
||||
|
||||
protected void onFailure(Call call, Exception e) {
|
||||
}
|
||||
|
||||
protected abstract void onResponse(T response);
|
||||
|
||||
public static class OKCallBackDefault extends OKCallBack<Response> {
|
||||
|
||||
@Override
|
||||
public Response onParseResponse(Call call, Response response) {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponse(Response response) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class OKCallBackString extends OKCallBack<String> {
|
||||
|
||||
@Override
|
||||
public void onError(Call call, Exception e) {
|
||||
setResult("");
|
||||
super.onError(call, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onParseResponse(Call call, Response response) {
|
||||
try {
|
||||
return response.body().string();
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Call call, Exception e) {
|
||||
setResult("");
|
||||
super.onFailure(call, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponse(String response) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.github.catvod.net;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
|
||||
class OKRequest {
|
||||
|
||||
private final String mMethodType;
|
||||
private final Map<String, String> mParamsMap;
|
||||
private final String mJsonStr;
|
||||
private final Map<String, String> mHeaderMap;
|
||||
private final OKCallBack mCallBack;
|
||||
private String mUrl;
|
||||
private Object mTag = null;
|
||||
private okhttp3.Request mOkHttpRequest;
|
||||
private okhttp3.Request.Builder mRequestBuilder;
|
||||
|
||||
OKRequest(String methodType, String url, Map<String, String> paramsMap, Map<String, String> headerMap, OKCallBack callBack) {
|
||||
this(methodType, url, null, paramsMap, headerMap, callBack);
|
||||
}
|
||||
|
||||
OKRequest(String methodType, String url, String jsonStr, Map<String, String> headerMap, OKCallBack callBack) {
|
||||
this(methodType, url, jsonStr, null, headerMap, callBack);
|
||||
}
|
||||
|
||||
private OKRequest(String methodType, String url, String jsonStr, Map<String, String> paramsMap, Map<String, String> headerMap, OKCallBack callBack) {
|
||||
mMethodType = methodType;
|
||||
mUrl = url;
|
||||
mJsonStr = jsonStr;
|
||||
mParamsMap = paramsMap;
|
||||
mHeaderMap = headerMap;
|
||||
mCallBack = callBack;
|
||||
getInstance();
|
||||
}
|
||||
|
||||
public void setTag(Object tag) {
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
private void getInstance() {
|
||||
mRequestBuilder = new okhttp3.Request.Builder();
|
||||
switch (mMethodType) {
|
||||
case OkHttpUtil.METHOD_GET:
|
||||
setGetParams();
|
||||
break;
|
||||
case OkHttpUtil.METHOD_POST:
|
||||
mRequestBuilder.post(getRequestBody());
|
||||
break;
|
||||
}
|
||||
mRequestBuilder.url(mUrl);
|
||||
if (mTag != null)
|
||||
mRequestBuilder.tag(mTag);
|
||||
if (mHeaderMap != null) {
|
||||
setHeader();
|
||||
}
|
||||
mOkHttpRequest = mRequestBuilder.build();
|
||||
}
|
||||
|
||||
private RequestBody getRequestBody() {
|
||||
if (!TextUtils.isEmpty(mJsonStr)) {
|
||||
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||
return RequestBody.create(JSON, mJsonStr);
|
||||
}
|
||||
FormBody.Builder formBody = new FormBody.Builder();
|
||||
if (mParamsMap != null) {
|
||||
for (String key : mParamsMap.keySet()) {
|
||||
formBody.add(key, mParamsMap.get(key));
|
||||
}
|
||||
}
|
||||
return formBody.build();
|
||||
}
|
||||
|
||||
private void setGetParams() {
|
||||
if (mParamsMap != null) {
|
||||
mUrl = mUrl + "?";
|
||||
for (String key : mParamsMap.keySet()) {
|
||||
mUrl = mUrl + key + "=" + mParamsMap.get(key) + "&";
|
||||
}
|
||||
mUrl = mUrl.substring(0, mUrl.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void setHeader() {
|
||||
if (mHeaderMap != null) {
|
||||
for (String key : mHeaderMap.keySet()) {
|
||||
mRequestBuilder.addHeader(key, mHeaderMap.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void execute(OkHttpClient client) {
|
||||
Call call = client.newCall(mOkHttpRequest);
|
||||
try {
|
||||
Response response = call.execute();
|
||||
if (mCallBack != null) {
|
||||
mCallBack.onSuccess(call, response);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (mCallBack != null) {
|
||||
mCallBack.onError(call, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
package com.github.catvod.net;
|
||||
|
||||
import com.github.catvod.crawler.Spider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Dns;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OkHttpUtil {
|
||||
|
||||
public static final String METHOD_GET = "GET";
|
||||
public static final String METHOD_POST = "POST";
|
||||
|
||||
private static final Object lockO = new Object();
|
||||
private static OkHttpClient defaultClient = null;
|
||||
private static OkHttpClient noRedirectClient = null;
|
||||
private static final int DEFAULT_TIMEOUT = 15;
|
||||
|
||||
public static OkHttpClient defaultClient() {
|
||||
synchronized (lockO) {
|
||||
if (defaultClient == null) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder().dns(safeDns()).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).retryOnConnectionFailure(true).sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert);
|
||||
defaultClient = builder.build();
|
||||
}
|
||||
return defaultClient;
|
||||
}
|
||||
}
|
||||
|
||||
public static OkHttpClient noRedirectClient() {
|
||||
synchronized (lockO) {
|
||||
if (noRedirectClient == null) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder().dns(safeDns()).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).followRedirects(false).followSslRedirects(false).retryOnConnectionFailure(true).sslSocketFactory(new SSLSocketFactoryCompat(SSLSocketFactoryCompat.trustAllCert), SSLSocketFactoryCompat.trustAllCert);
|
||||
noRedirectClient = builder.build();
|
||||
}
|
||||
return noRedirectClient;
|
||||
}
|
||||
}
|
||||
|
||||
public static Dns safeDns() {
|
||||
try {
|
||||
return (Dns) Spider.class.getMethod("safeDns").invoke(null);
|
||||
} catch (Exception e) {
|
||||
return Dns.SYSTEM;
|
||||
}
|
||||
}
|
||||
|
||||
public static String string(OkHttpClient client, String url, String tag, Map<String, String> paramsMap, Map<String, String> headerMap, Map<String, List<String>> respHeaderMap) {
|
||||
return string(client, url, tag, paramsMap, headerMap, respHeaderMap, OkHttpUtil.METHOD_GET);
|
||||
}
|
||||
|
||||
public static String string(OkHttpClient client, String url, String tag, Map<String, String> paramsMap, Map<String, String> headerMap, Map<String, List<String>> respHeaderMap, String httpMethod) {
|
||||
OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString() {
|
||||
@Override
|
||||
public String onParseResponse(Call call, Response response) {
|
||||
try {
|
||||
if (respHeaderMap != null) {
|
||||
respHeaderMap.clear();
|
||||
respHeaderMap.putAll(response.headers().toMultimap());
|
||||
}
|
||||
return response.body().string();
|
||||
} catch (IOException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
||||
OKRequest req = new OKRequest(httpMethod, url, paramsMap, headerMap, callback);
|
||||
req.setTag(tag);
|
||||
req.execute(client);
|
||||
return callback.getResult();
|
||||
}
|
||||
|
||||
public static String stringNoRedirect(String url, Map<String, String> headerMap, Map<String, List<String>> respHeaderMap) {
|
||||
return string(noRedirectClient(), url, null, null, headerMap, respHeaderMap);
|
||||
}
|
||||
|
||||
public static String string(String url) {
|
||||
return string(defaultClient(), url, null, null, null, null);
|
||||
}
|
||||
|
||||
public static String string(String url, Map<String, String> headerMap) {
|
||||
return string(defaultClient(), url, null, null, headerMap, null);
|
||||
}
|
||||
|
||||
public static String string(String url, Map<String, String> headerMap, Map<String, List<String>> respHeaderMap) {
|
||||
return string(defaultClient(), url, null, null, headerMap, respHeaderMap);
|
||||
}
|
||||
|
||||
public static String string(String url, String tag, Map<String, String> headerMap) {
|
||||
return string(defaultClient(), url, tag, null, headerMap, null);
|
||||
}
|
||||
|
||||
public static void get(OkHttpClient client, String url, OKCallBack callBack) {
|
||||
get(client, url, null, null, callBack);
|
||||
}
|
||||
|
||||
public static void get(OkHttpClient client, String url, Map<String, String> paramsMap, OKCallBack callBack) {
|
||||
get(client, url, paramsMap, null, callBack);
|
||||
}
|
||||
|
||||
public static void get(OkHttpClient client, String url, Map<String, String> paramsMap, Map<String, String> headerMap, OKCallBack callBack) {
|
||||
new OKRequest(METHOD_GET, url, paramsMap, headerMap, callBack).execute(client);
|
||||
}
|
||||
|
||||
public static String post(String url) {
|
||||
return post(url, null);
|
||||
}
|
||||
|
||||
public static String post(String url, Map<String, String> paramsMap) {
|
||||
return post(url, paramsMap, null);
|
||||
}
|
||||
|
||||
public static String post(String url, Map<String, String> paramsMap, Map<String, String> headerMap) {
|
||||
OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString();
|
||||
new OKRequest(METHOD_POST, url, paramsMap, headerMap, callback).execute(defaultClient());
|
||||
return callback.getResult();
|
||||
}
|
||||
|
||||
public static String postJson(String url, String jsonStr, Map<String, String> headerMap) {
|
||||
OKCallBack.OKCallBackString callback = new OKCallBack.OKCallBackString();
|
||||
new OKRequest(METHOD_POST, url, jsonStr, headerMap, callback).execute(defaultClient());
|
||||
return callback.getResult();
|
||||
}
|
||||
|
||||
public static void cancel(OkHttpClient client, Object tag) {
|
||||
if (client == null || tag == null) return;
|
||||
for (Call call : client.dispatcher().queuedCalls()) {
|
||||
if (tag.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
for (Call call : client.dispatcher().runningCalls()) {
|
||||
if (tag.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void cancel(Object tag) {
|
||||
cancel(defaultClient(), tag);
|
||||
}
|
||||
|
||||
public static String getRedirectLocation(Map<String, List<String>> headers) {
|
||||
if (headers == null) return null;
|
||||
if (headers.containsKey("location")) return headers.get("location").get(0);
|
||||
if (headers.containsKey("Location")) return headers.get("Location").get(0);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.github.catvod.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class SSLSocketFactoryCompat extends SSLSocketFactory {
|
||||
|
||||
public static final X509TrustManager trustAllCert = new X509TrustManager() {
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[]{};
|
||||
}
|
||||
};
|
||||
|
||||
static String[] protocols = null;
|
||||
static String[] cipherSuites = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
|
||||
if (socket != null) {
|
||||
List<String> protocols = new LinkedList<>();
|
||||
for (String protocol : socket.getSupportedProtocols()) if (!protocol.toUpperCase().contains("SSL")) protocols.add(protocol);
|
||||
SSLSocketFactoryCompat.protocols = protocols.toArray(new String[protocols.size()]);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final SSLSocketFactory defaultFactory;
|
||||
|
||||
public SSLSocketFactoryCompat(X509TrustManager tm) {
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null);
|
||||
defaultFactory = sslContext.getSocketFactory();
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AssertionError(); // The system has no TLS. Just give up.
|
||||
}
|
||||
}
|
||||
|
||||
private void upgradeTLS(SSLSocket ssl) {
|
||||
if (protocols != null) {
|
||||
ssl.setEnabledProtocols(protocols);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return cipherSuites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return cipherSuites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
Socket ssl = defaultFactory.createSocket(s, host, port, autoClose);
|
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
|
||||
return ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
Socket ssl = defaultFactory.createSocket(host, port);
|
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
|
||||
return ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort);
|
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
|
||||
return ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
Socket ssl = defaultFactory.createSocket(host, port);
|
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
|
||||
return ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort);
|
||||
if (ssl instanceof SSLSocket) upgradeTLS((SSLSocket) ssl);
|
||||
return ssl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package com.github.catvod.parser;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.net.OkHttpUtil;
|
||||
import com.github.catvod.utils.Misc;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
public class JsonBasic {
|
||||
|
||||
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
|
||||
SpiderDebug.log("Load Json Parse Basic...");
|
||||
if (jx.isEmpty()) return new JSONObject();
|
||||
Set<String> jxNames = jx.keySet();
|
||||
for (String jxName : jxNames) {
|
||||
String parseUrl = jx.get(jxName);
|
||||
HashMap<String, String> reqHeaders = getReqHeader(parseUrl);
|
||||
try {
|
||||
String realUrl = reqHeaders.get("url");
|
||||
reqHeaders.remove("url");
|
||||
SpiderDebug.log(realUrl + url);
|
||||
String json = OkHttpUtil.string(realUrl + url, reqHeaders);
|
||||
JSONObject taskResult = Misc.jsonParse(url, json);
|
||||
if (taskResult == null) continue;
|
||||
taskResult.put("jxFrom", jxName);
|
||||
SpiderDebug.log(taskResult.toString());
|
||||
return taskResult;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getReqHeader(String url) {
|
||||
HashMap<String, String> reqHeaders = new HashMap<>();
|
||||
reqHeaders.put("url", url);
|
||||
if (!url.contains("cat_ext")) return reqHeaders;
|
||||
try {
|
||||
int start = url.indexOf("cat_ext=");
|
||||
int end = url.indexOf("&", start);
|
||||
String ext = url.substring(start + 8, end);
|
||||
ext = new String(Base64.decode(ext, Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP));
|
||||
String newUrl = url.substring(0, start) + url.substring(end + 1);
|
||||
JSONObject jsonObject = new JSONObject(ext);
|
||||
if (jsonObject.has("header")) {
|
||||
JSONObject headerJson = jsonObject.optJSONObject("header");
|
||||
Iterator<String> keys = headerJson.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
reqHeaders.put(key, headerJson.optString(key, ""));
|
||||
}
|
||||
}
|
||||
reqHeaders.put("url", newUrl);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return reqHeaders;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.github.catvod.parser;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.net.OkHttpUtil;
|
||||
import com.github.catvod.utils.Misc;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletionService;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class JsonParallel {
|
||||
|
||||
private static final String ParseOKTag = "p_json_parse";
|
||||
|
||||
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
|
||||
if (jx.isEmpty()) return new JSONObject();
|
||||
ExecutorService service = Executors.newFixedThreadPool(3);
|
||||
CompletionService<JSONObject> completionService = new ExecutorCompletionService<>(service);
|
||||
List<Future<JSONObject>> futures = new ArrayList<>();
|
||||
Set<String> jxNames = jx.keySet();
|
||||
for (String jxName : jxNames) {
|
||||
String parseUrl = jx.get(jxName);
|
||||
futures.add(completionService.submit(() -> {
|
||||
try {
|
||||
HashMap<String, String> reqHeaders = JsonBasic.getReqHeader(parseUrl);
|
||||
String realUrl = reqHeaders.get("url");
|
||||
reqHeaders.remove("url");
|
||||
SpiderDebug.log(realUrl + url);
|
||||
String json = OkHttpUtil.string(realUrl + url, ParseOKTag, reqHeaders);
|
||||
JSONObject taskResult = Misc.jsonParse(url, json);
|
||||
taskResult.put("jxFrom", jxName);
|
||||
SpiderDebug.log(taskResult.toString());
|
||||
return taskResult;
|
||||
} catch (Exception ignored) {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
}
|
||||
JSONObject pTaskResult = null;
|
||||
for (int i = 0; i < futures.size(); ++i) {
|
||||
try {
|
||||
Future<JSONObject> completed = completionService.take();
|
||||
pTaskResult = completed.get();
|
||||
if (pTaskResult != null) {
|
||||
OkHttpUtil.cancel(ParseOKTag);
|
||||
for (int j = 0; j < futures.size(); j++) {
|
||||
try {
|
||||
futures.get(j).cancel(true);
|
||||
} catch (Throwable th) {
|
||||
SpiderDebug.log(th);
|
||||
}
|
||||
}
|
||||
futures.clear();
|
||||
break;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
service.shutdownNow();
|
||||
return pTaskResult != null ? pTaskResult : new JSONObject();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.github.catvod.parser;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.net.OkHttpUtil;
|
||||
import com.github.catvod.utils.Misc;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
public class JsonSequence {
|
||||
|
||||
public static JSONObject parse(LinkedHashMap<String, String> jx, String url) {
|
||||
if (jx.isEmpty()) return new JSONObject();
|
||||
Set<String> jxNames = jx.keySet();
|
||||
for (String jxName : jxNames) {
|
||||
try {
|
||||
String parseUrl = jx.get(jxName);
|
||||
HashMap<String, String> reqHeaders = JsonBasic.getReqHeader(parseUrl);
|
||||
String realUrl = reqHeaders.get("url");
|
||||
reqHeaders.remove("url");
|
||||
SpiderDebug.log(realUrl + url);
|
||||
String json = OkHttpUtil.string(realUrl + url, reqHeaders);
|
||||
JSONObject taskResult = Misc.jsonParse(url, json);
|
||||
if (taskResult == null) continue;
|
||||
taskResult.put("jxFrom", jxName);
|
||||
return taskResult;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package com.github.catvod.parser;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class MixDemo {
|
||||
|
||||
private static final HashMap<String, ArrayList<String>> flagWebJx = new HashMap<>();
|
||||
private static HashMap<String, ArrayList<String>> configs = null;
|
||||
|
||||
private static void setConfigs(LinkedHashMap<String, HashMap<String, String>> jx) {
|
||||
configs = new HashMap<>();
|
||||
for (String key : jx.keySet()) {
|
||||
HashMap<String, String> parseBean = jx.get(key);
|
||||
String type = parseBean.get("type");
|
||||
if (type.equals("1") || type.equals("0")) {
|
||||
try {
|
||||
JSONArray flags = new JSONObject(parseBean.get("ext")).getJSONArray("flag");
|
||||
for (int j = 0; j < flags.length(); j++) {
|
||||
String flagKey = flags.getString(j);
|
||||
ArrayList<String> flagJx = configs.get(flagKey);
|
||||
if (flagJx == null) {
|
||||
flagJx = new ArrayList<>();
|
||||
configs.put(flagKey, flagJx);
|
||||
}
|
||||
flagJx.add(key);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static JSONObject parse(LinkedHashMap<String, HashMap<String, String>> jx, String nameMe, String flag, String url) {
|
||||
try {
|
||||
if (configs == null) setConfigs(jx);
|
||||
LinkedHashMap<String, String> jsonJx = new LinkedHashMap<>();
|
||||
ArrayList<String> webJx = new ArrayList<>();
|
||||
ArrayList<String> flagJx = configs.get(flag);
|
||||
if (flagJx != null && !flagJx.isEmpty()) {
|
||||
for (int i = 0; i < flagJx.size(); i++) {
|
||||
String key = flagJx.get(i);
|
||||
HashMap<String, String> parseBean = jx.get(key);
|
||||
String type = parseBean.get("type");
|
||||
if (type.equals("1")) {
|
||||
jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext")));
|
||||
} else if (type.equals("0")) {
|
||||
webJx.add(parseBean.get("url"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (String key : jx.keySet()) {
|
||||
HashMap<String, String> parseBean = jx.get(key);
|
||||
String type = parseBean.get("type");
|
||||
if (type.equals("1")) {
|
||||
jsonJx.put(key, mixUrl(parseBean.get("url"), parseBean.get("ext")));
|
||||
} else if (type.equals("0")) {
|
||||
webJx.add(parseBean.get("url"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!webJx.isEmpty()) flagWebJx.put(flag, webJx);
|
||||
JSONObject jsonResult = JsonParallel.parse(jsonJx, url);
|
||||
if (jsonResult.has("url")) return jsonResult;
|
||||
if (!webJx.isEmpty()) {
|
||||
JSONObject webResult = new JSONObject();
|
||||
webResult.put("url", "proxy://do=parseMix&flag=" + flag + "&url=" + Base64.encodeToString(url.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP));
|
||||
webResult.put("parse", 1);
|
||||
return webResult;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
private static String mixUrl(String url, String ext) {
|
||||
if (ext.trim().isEmpty()) return url;
|
||||
int index = url.indexOf("?");
|
||||
if (index == -1) return url;
|
||||
return url.substring(0, index + 1) + "cat_ext=" + Base64.encodeToString(ext.getBytes(), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP) + "&" + url.substring(index + 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
|
||||
public class Init {
|
||||
|
||||
private final Handler mHandler;
|
||||
private Application mApp;
|
||||
|
||||
private static class Loader {
|
||||
static volatile Init INSTANCE = new Init();
|
||||
}
|
||||
|
||||
private static Init get() {
|
||||
return Loader.INSTANCE;
|
||||
}
|
||||
|
||||
public Init() {
|
||||
this.mHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
public static void init(Context context) {
|
||||
SpiderDebug.log("自定義爬蟲代碼載入成功!");
|
||||
get().mApp = ((Application) context);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.github.catvod.spider;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import com.github.catvod.crawler.Spider;
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
import com.github.catvod.live.TxtSubscribe;
|
||||
import com.github.catvod.net.OkHttpUtil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Proxy extends Spider {
|
||||
|
||||
private static int port = -1;
|
||||
|
||||
public static Object[] proxy(Map<String, String> params) {
|
||||
switch (Objects.requireNonNull(params.get("do"))) {
|
||||
case "ck":
|
||||
return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes(StandardCharsets.UTF_8))};
|
||||
case "live":
|
||||
return TxtSubscribe.load(new String(Base64.decode(params.get("ext"), Base64.DEFAULT | Base64.URL_SAFE | Base64.NO_WRAP), StandardCharsets.UTF_8));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static void adjustPort() {
|
||||
if (Proxy.port > 0) return;
|
||||
int port = 9978;
|
||||
while (port < 10000) {
|
||||
String resp = OkHttpUtil.string("http://127.0.0.1:" + port + "/proxy?do=ck", null);
|
||||
if (resp.equals("ok")) {
|
||||
SpiderDebug.log("Found local server port " + port);
|
||||
Proxy.port = port;
|
||||
break;
|
||||
}
|
||||
port++;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrl() {
|
||||
adjustPort();
|
||||
return "http://127.0.0.1:" + port + "/proxy";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package com.github.catvod.utils;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Misc {
|
||||
|
||||
public static final String CHROME = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.62 Safari/537.36";
|
||||
private static final Pattern snifferMatch = Pattern.compile("http((?!http).){20,}?\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg)\\?.*|http((?!http).){20,}\\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg)|http((?!http).){20,}?\\/m3u8\\?pt=m3u8.*|http((?!http).)*?default\\.ixigua\\.com\\/.*|http((?!http).)*?cdn-tos[^\\?]*|http((?!http).)*?\\/obj\\/tos[^\\?]*|http.*?\\/player\\/m3u8play\\.php\\?url=.*|http.*?\\/player\\/.*?[pP]lay\\.php\\?url=.*|http.*?\\/playlist\\/m3u8\\/\\?vid=.*|http.*?\\.php\\?type=m3u8&.*|http.*?\\/download.aspx\\?.*|http.*?\\/api\\/up_api.php\\?.*|https.*?\\.66yk\\.cn.*|http((?!http).)*?netease\\.com\\/file\\/.*");
|
||||
|
||||
public static boolean isVip(String url) {
|
||||
try {
|
||||
boolean isVip = false;
|
||||
String host = Uri.parse(url).getHost();
|
||||
String[] vipWebsites = new String[]{"iqiyi.com", "v.qq.com", "youku.com", "le.com", "tudou.com", "mgtv.com", "sohu.com", "acfun.cn", "bilibili.com", "baofeng.com", "pptv.com"};
|
||||
for (String vipWebsite : vipWebsites) {
|
||||
if (host.contains(vipWebsite)) {
|
||||
if ("iqiyi.com".equals(vipWebsite)) {
|
||||
if (url.contains("iqiyi.com/a_") || url.contains("iqiyi.com/w_") || url.contains("iqiyi.com/v_")) {
|
||||
isVip = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
isVip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isVip;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isVideoFormat(String url) {
|
||||
if (snifferMatch.matcher(url).find()) {
|
||||
return !url.contains("cdn-tos") || !url.contains(".js");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String fixUrl(String base, String src) {
|
||||
try {
|
||||
if (src.startsWith("//")) {
|
||||
Uri parse = Uri.parse(base);
|
||||
src = parse.getScheme() + ":" + src;
|
||||
} else if (!src.contains("://")) {
|
||||
Uri parse = Uri.parse(base);
|
||||
src = parse.getScheme() + "://" + parse.getHost() + src;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log(e);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
public static JSONObject fixJsonVodHeader(JSONObject headers, String input, String url) throws JSONException {
|
||||
if (headers == null)
|
||||
headers = new JSONObject();
|
||||
if (input.contains("www.mgtv.com")) {
|
||||
headers.put("Referer", " ");
|
||||
headers.put("User-Agent", " Mozilla/5.0");
|
||||
} else if (url.contains("titan.mgtv")) {
|
||||
headers.put("Referer", " ");
|
||||
headers.put("User-Agent", " Mozilla/5.0");
|
||||
} else if (input.contains("bilibili")) {
|
||||
headers.put("Referer", " https://www.bilibili.com/");
|
||||
headers.put("User-Agent", " " + Misc.CHROME);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
public static JSONObject jsonParse(String input, String json) throws JSONException {
|
||||
JSONObject jsonPlayData = new JSONObject(json);
|
||||
String url = jsonPlayData.getString("url");
|
||||
if (url.startsWith("//")) {
|
||||
url = "https:" + url;
|
||||
}
|
||||
if (!url.startsWith("http")) {
|
||||
return null;
|
||||
}
|
||||
if (url.equals(input)) {
|
||||
if (isVip(url) || !isVideoFormat(url)) return null;
|
||||
}
|
||||
JSONObject headers = new JSONObject();
|
||||
String ua = jsonPlayData.optString("user-agent", "");
|
||||
if (ua.trim().length() > 0) {
|
||||
headers.put("User-Agent", " " + ua);
|
||||
}
|
||||
String referer = jsonPlayData.optString("referer", "");
|
||||
if (referer.trim().length() > 0) {
|
||||
headers.put("Referer", " " + referer);
|
||||
}
|
||||
headers = Misc.fixJsonVodHeader(headers, input, url);
|
||||
JSONObject taskResult = new JSONObject();
|
||||
taskResult.put("header", headers);
|
||||
taskResult.put("url", url);
|
||||
return taskResult;
|
||||
}
|
||||
|
||||
public static String MD5(String src) {
|
||||
return MD5(src, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static String MD5(String src, Charset charset) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] messageDigest = md.digest(src.getBytes(charset));
|
||||
BigInteger no = new BigInteger(1, messageDigest);
|
||||
StringBuilder sb = new StringBuilder(no.toString(16));
|
||||
while (sb.length() < 32) sb.insert(0, "0");
|
||||
return sb.toString().toLowerCase();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,686 @@
|
|||
package com.github.catvod.xpath;
|
||||
|
||||
import com.github.catvod.crawler.SpiderDebug;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class XPathRule {
|
||||
/**
|
||||
* user-agent
|
||||
*/
|
||||
private String ua;
|
||||
/**
|
||||
* 取得分類和首頁推薦的Url
|
||||
*/
|
||||
private String homeUrl;
|
||||
/**
|
||||
* 分類節點 xpath
|
||||
*/
|
||||
private String cateNode;
|
||||
/**
|
||||
* 分類節點名 xpath
|
||||
*/
|
||||
private String cateName;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateNameR;
|
||||
/**
|
||||
* 分類節點 id xpath
|
||||
*/
|
||||
private String cateId;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateIdR;
|
||||
/**
|
||||
* 手動指定分類如果有則不從 homeUrl 中獲取分類
|
||||
*/
|
||||
private final LinkedHashMap<String, String> cateManual = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* 篩選
|
||||
*/
|
||||
private JSONObject filter;
|
||||
|
||||
/**
|
||||
* 更新推薦影片節點 xpath
|
||||
*/
|
||||
private String homeVodNode;
|
||||
/**
|
||||
* 更新推薦影片名稱 xpath
|
||||
*/
|
||||
private String homeVodName;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern homeVodNameR;
|
||||
/**
|
||||
* 更新推薦影片 id xpath
|
||||
*/
|
||||
private String homeVodId;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern homeVodIdR;
|
||||
/**
|
||||
* 更新推薦影片圖片 xpath
|
||||
*/
|
||||
private String homeVodImg;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern homeVodImgR;
|
||||
/**
|
||||
* 更新推薦影片簡介 xpath
|
||||
*/
|
||||
private String homeVodMark;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern homeVodMarkR;
|
||||
/**
|
||||
* 分類頁地址
|
||||
*/
|
||||
private String cateUrl;
|
||||
/**
|
||||
* 分類頁影片節點 xpath
|
||||
*/
|
||||
private String cateVodNode;
|
||||
/**
|
||||
* 分類頁影片名稱 xpath
|
||||
*/
|
||||
private String cateVodName;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateVodNameR;
|
||||
/**
|
||||
* 分類頁影片影片id xpath
|
||||
*/
|
||||
private String cateVodId;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateVodIdR;
|
||||
/**
|
||||
* 分類頁影片影片圖片 xpath
|
||||
*/
|
||||
private String cateVodImg;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateVodImgR;
|
||||
/**
|
||||
* 分類頁影片影片簡介 xpath
|
||||
*/
|
||||
private String cateVodMark;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern cateVodMarkR;
|
||||
|
||||
/**
|
||||
* 詳情頁面
|
||||
*/
|
||||
private String dtUrl;
|
||||
/**
|
||||
* 詳情節點 xpath
|
||||
*/
|
||||
private String dtNode;
|
||||
/**
|
||||
* 詳情影片 xpath
|
||||
*/
|
||||
private String dtName;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtNameR;
|
||||
/**
|
||||
* 詳情影片圖片 xpath
|
||||
*/
|
||||
private String dtImg;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtImgR;
|
||||
/**
|
||||
* 詳情影片分類 xpath
|
||||
*/
|
||||
private String dtCate;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtCateR;
|
||||
/**
|
||||
* 詳情影片年份 xpath
|
||||
*/
|
||||
private String dtYear;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtYearR;
|
||||
/**
|
||||
* 詳情影片地區 xpath
|
||||
*/
|
||||
private String dtArea;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtAreaR;
|
||||
/**
|
||||
* 詳情影片簡介 xpath
|
||||
*/
|
||||
private String dtMark;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtMarkR;
|
||||
/**
|
||||
* 詳情演員 xpath
|
||||
*/
|
||||
private String dtActor;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtActorR;
|
||||
/**
|
||||
* 詳情導演 xpath
|
||||
*/
|
||||
private String dtDirector;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtDirectorR;
|
||||
/**
|
||||
* 詳情說明 xpath
|
||||
*/
|
||||
private String dtDesc;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern dtDescR;
|
||||
|
||||
/**
|
||||
* 詳情播放來源節點
|
||||
*/
|
||||
private String dtFromNode;
|
||||
/**
|
||||
* 詳情播放來源名稱 xpath
|
||||
*/
|
||||
private String dtFromName;
|
||||
/**
|
||||
* 詳情
|
||||
*/
|
||||
private Pattern dtFromNameR;
|
||||
/**
|
||||
* 詳情播放地址列表節點 xpath
|
||||
*/
|
||||
private String dtUrlNode;
|
||||
/**
|
||||
* 詳情播放地址節點 xpath
|
||||
*/
|
||||
private String dtUrlSubNode;
|
||||
/**
|
||||
* 詳情播放地址id xpath
|
||||
*/
|
||||
private String dtUrlId;
|
||||
/**
|
||||
* 詳情
|
||||
*/
|
||||
private Pattern dtUrlIdR;
|
||||
/**
|
||||
* 詳情播放地址名稱 xpath
|
||||
*/
|
||||
private String dtUrlName;
|
||||
/**
|
||||
* 詳情
|
||||
*/
|
||||
private Pattern dtUrlNameR;
|
||||
/**
|
||||
* 播放頁面url
|
||||
*/
|
||||
private String playUrl;
|
||||
/**
|
||||
* 播放解析調用ua
|
||||
*/
|
||||
private String playUa;
|
||||
|
||||
/**
|
||||
* 搜尋頁地址
|
||||
*/
|
||||
private String searchUrl;
|
||||
|
||||
/**
|
||||
* 搜尋頁影片節點 xpath
|
||||
*/
|
||||
private String scVodNode;
|
||||
/**
|
||||
* 搜尋頁影片名稱 xpath
|
||||
*/
|
||||
private String scVodName;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern scVodNameR;
|
||||
/**
|
||||
* 搜尋頁影片id xpath
|
||||
*/
|
||||
private String scVodId;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern scVodIdR;
|
||||
/**
|
||||
* 搜尋頁影片圖片 xpath
|
||||
*/
|
||||
private String scVodImg;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern scVodImgR;
|
||||
/**
|
||||
* 搜尋頁影片簡介 xpath
|
||||
*/
|
||||
private String scVodMark;
|
||||
/**
|
||||
* 正則對取到的數據進行二次處理
|
||||
*/
|
||||
private Pattern scVodMarkR;
|
||||
|
||||
private static Pattern getPattern(JSONObject json, String key) {
|
||||
String v = json.optString(key).trim();
|
||||
if (v.isEmpty())
|
||||
return null;
|
||||
else {
|
||||
try {
|
||||
return Pattern.compile(v);
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String doReplaceRegex(Pattern pattern, String src) {
|
||||
if (pattern == null)
|
||||
return src;
|
||||
try {
|
||||
Matcher matcher = pattern.matcher(src);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1).trim();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log(e);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
public static XPathRule fromJson(String json) {
|
||||
try {
|
||||
JSONObject jsonObj = new JSONObject(json);
|
||||
XPathRule rule = new XPathRule();
|
||||
rule.ua = jsonObj.optString("ua");
|
||||
rule.homeUrl = jsonObj.optString("homeUrl").trim();
|
||||
rule.cateNode = jsonObj.optString("cateNode").trim();
|
||||
rule.cateName = jsonObj.optString("cateName").trim();
|
||||
rule.cateNameR = getPattern(jsonObj, "cateNameR");
|
||||
rule.cateId = jsonObj.optString("cateId").trim();
|
||||
rule.cateIdR = getPattern(jsonObj, "cateIdR");
|
||||
JSONObject navs = jsonObj.optJSONObject("cateManual");
|
||||
if (navs != null) {
|
||||
Iterator<String> keys = navs.keys();
|
||||
while (keys.hasNext()) {
|
||||
String name = keys.next();
|
||||
rule.cateManual.put(name.trim(), navs.getString(name).trim());
|
||||
}
|
||||
}
|
||||
rule.filter = jsonObj.optJSONObject("filter");
|
||||
rule.homeVodNode = jsonObj.optString("homeVodNode").trim();
|
||||
rule.homeVodName = jsonObj.optString("homeVodName").trim();
|
||||
rule.homeVodNameR = getPattern(jsonObj, "homeVodNameR");
|
||||
rule.homeVodId = jsonObj.optString("homeVodId").trim();
|
||||
rule.homeVodIdR = getPattern(jsonObj, "homeVodIdR");
|
||||
rule.homeVodImg = jsonObj.optString("homeVodImg").trim();
|
||||
rule.homeVodImgR = getPattern(jsonObj, "homeVodImgR");
|
||||
rule.homeVodMark = jsonObj.optString("homeVodMark").trim();
|
||||
rule.homeVodMarkR = getPattern(jsonObj, "homeVodMarkR");
|
||||
rule.cateUrl = jsonObj.optString("cateUrl").trim();
|
||||
rule.cateVodNode = jsonObj.optString("cateVodNode").trim();
|
||||
rule.cateVodName = jsonObj.optString("cateVodName").trim();
|
||||
rule.cateVodNameR = getPattern(jsonObj, "cateVodNameR");
|
||||
rule.cateVodId = jsonObj.optString("cateVodId").trim();
|
||||
rule.cateVodIdR = getPattern(jsonObj, "cateVodIdR");
|
||||
rule.cateVodImg = jsonObj.optString("cateVodImg").trim();
|
||||
rule.cateVodImgR = getPattern(jsonObj, "cateVodImgR");
|
||||
rule.cateVodMark = jsonObj.optString("cateVodMark").trim();
|
||||
rule.cateVodMarkR = getPattern(jsonObj, "cateVodMarkR");
|
||||
rule.dtUrl = jsonObj.optString("dtUrl");
|
||||
rule.dtNode = jsonObj.optString("dtNode");
|
||||
rule.dtName = jsonObj.optString("dtName");
|
||||
rule.dtNameR = getPattern(jsonObj, "dtNameR");
|
||||
rule.dtImg = jsonObj.optString("dtImg");
|
||||
rule.dtImgR = getPattern(jsonObj, "dtImgR");
|
||||
rule.dtCate = jsonObj.optString("dtCate");
|
||||
rule.dtCateR = getPattern(jsonObj, "dtCateR");
|
||||
rule.dtYear = jsonObj.optString("dtYear");
|
||||
rule.dtYearR = getPattern(jsonObj, "dtYearR");
|
||||
rule.dtArea = jsonObj.optString("dtArea");
|
||||
rule.dtAreaR = getPattern(jsonObj, "dtAreaR");
|
||||
rule.dtMark = jsonObj.optString("dtMark");
|
||||
rule.dtMarkR = getPattern(jsonObj, "dtMarkR");
|
||||
rule.dtActor = jsonObj.optString("dtActor");
|
||||
rule.dtActorR = getPattern(jsonObj, "dtActorR");
|
||||
rule.dtDirector = jsonObj.optString("dtDirector");
|
||||
rule.dtDirectorR = getPattern(jsonObj, "dtDirectorR");
|
||||
rule.dtDesc = jsonObj.optString("dtDesc");
|
||||
rule.dtDescR = getPattern(jsonObj, "dtDescR");
|
||||
rule.dtFromNode = jsonObj.optString("dtFromNode");
|
||||
rule.dtFromName = jsonObj.optString("dtFromName");
|
||||
rule.dtFromNameR = getPattern(jsonObj, "dtFromNameR");
|
||||
rule.dtUrlNode = jsonObj.optString("dtUrlNode");
|
||||
rule.dtUrlSubNode = jsonObj.optString("dtUrlSubNode");
|
||||
rule.dtUrlId = jsonObj.optString("dtUrlId");
|
||||
rule.dtUrlIdR = getPattern(jsonObj, "dtUrlIdR");
|
||||
rule.dtUrlName = jsonObj.optString("dtUrlName");
|
||||
rule.dtUrlNameR = getPattern(jsonObj, "dtUrlNameR");
|
||||
rule.playUrl = jsonObj.optString("playUrl");
|
||||
rule.playUa = jsonObj.optString("playUa");
|
||||
rule.searchUrl = jsonObj.optString("searchUrl");
|
||||
rule.scVodNode = jsonObj.optString("scVodNode").trim();
|
||||
rule.scVodName = jsonObj.optString("scVodName").trim();
|
||||
rule.scVodNameR = getPattern(jsonObj, "scVodNameR");
|
||||
rule.scVodId = jsonObj.optString("scVodId").trim();
|
||||
rule.scVodIdR = getPattern(jsonObj, "scVodIdR");
|
||||
rule.scVodImg = jsonObj.optString("scVodImg").trim();
|
||||
rule.scVodImgR = getPattern(jsonObj, "scVodImgR");
|
||||
rule.scVodMark = jsonObj.optString("scVodMark").trim();
|
||||
rule.scVodMarkR = getPattern(jsonObj, "scVodMarkR");
|
||||
return rule;
|
||||
} catch (Exception e) {
|
||||
SpiderDebug.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getUa() {
|
||||
return ua;
|
||||
}
|
||||
|
||||
public String getHomeUrl() {
|
||||
return homeUrl;
|
||||
}
|
||||
|
||||
public String getCateNode() {
|
||||
return cateNode;
|
||||
}
|
||||
|
||||
public String getCateName() {
|
||||
return cateName;
|
||||
}
|
||||
|
||||
public String getCateNameR(String src) {
|
||||
return doReplaceRegex(cateNameR, src);
|
||||
}
|
||||
|
||||
public String getCateId() {
|
||||
return cateId;
|
||||
}
|
||||
|
||||
public String getCateIdR(String src) {
|
||||
return doReplaceRegex(cateIdR, src);
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, String> getCateManual() {
|
||||
return cateManual;
|
||||
}
|
||||
|
||||
public JSONObject getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public String getHomeVodNode() {
|
||||
return homeVodNode;
|
||||
}
|
||||
|
||||
public String getHomeVodName() {
|
||||
return homeVodName;
|
||||
}
|
||||
|
||||
public String getHomeVodNameR(String src) {
|
||||
return doReplaceRegex(homeVodNameR, src);
|
||||
}
|
||||
|
||||
public String getHomeVodId() {
|
||||
return homeVodId;
|
||||
}
|
||||
|
||||
public String getHomeVodIdR(String src) {
|
||||
return doReplaceRegex(homeVodIdR, src);
|
||||
}
|
||||
|
||||
public String getHomeVodImg() {
|
||||
return homeVodImg;
|
||||
}
|
||||
|
||||
public String getHomeVodImgR(String src) {
|
||||
return doReplaceRegex(homeVodImgR, src);
|
||||
}
|
||||
|
||||
public String getHomeVodMark() {
|
||||
return homeVodMark;
|
||||
}
|
||||
|
||||
public String getHomeVodMarkR(String src) {
|
||||
return doReplaceRegex(homeVodMarkR, src);
|
||||
}
|
||||
|
||||
public String getCateUrl() {
|
||||
return cateUrl;
|
||||
}
|
||||
|
||||
public String getCateVodNode() {
|
||||
return cateVodNode;
|
||||
}
|
||||
|
||||
public String getCateVodName() {
|
||||
return cateVodName;
|
||||
}
|
||||
|
||||
public String getCateVodNameR(String src) {
|
||||
return doReplaceRegex(cateVodNameR, src);
|
||||
}
|
||||
|
||||
public String getCateVodId() {
|
||||
return cateVodId;
|
||||
}
|
||||
|
||||
public String getCateVodIdR(String src) {
|
||||
return doReplaceRegex(cateVodIdR, src);
|
||||
}
|
||||
|
||||
public String getCateVodImg() {
|
||||
return cateVodImg;
|
||||
}
|
||||
|
||||
public String getCateVodImgR(String src) {
|
||||
return doReplaceRegex(cateVodImgR, src);
|
||||
}
|
||||
|
||||
public String getCateVodMark() {
|
||||
return cateVodMark;
|
||||
}
|
||||
|
||||
public String getCateVodMarkR(String src) {
|
||||
return doReplaceRegex(cateVodNameR, src);
|
||||
}
|
||||
|
||||
public String getDetailUrl() {
|
||||
return dtUrl;
|
||||
}
|
||||
|
||||
public String getDetailNode() {
|
||||
return dtNode;
|
||||
}
|
||||
|
||||
public String getDetailName() {
|
||||
return dtName;
|
||||
}
|
||||
|
||||
public String getDetailNameR(String src) {
|
||||
return doReplaceRegex(dtNameR, src);
|
||||
}
|
||||
|
||||
public String getDetailImg() {
|
||||
return dtImg;
|
||||
}
|
||||
|
||||
public String getDetailImgR(String src) {
|
||||
return doReplaceRegex(dtImgR, src);
|
||||
}
|
||||
|
||||
public String getDetailCate() {
|
||||
return dtCate;
|
||||
}
|
||||
|
||||
public String getDetailCateR(String src) {
|
||||
return doReplaceRegex(dtCateR, src);
|
||||
}
|
||||
|
||||
public String getDetailYear() {
|
||||
return dtYear;
|
||||
}
|
||||
|
||||
public String getDetailYearR(String src) {
|
||||
return doReplaceRegex(dtYearR, src);
|
||||
}
|
||||
|
||||
public String getDetailArea() {
|
||||
return dtArea;
|
||||
}
|
||||
|
||||
public String getDetailAreaR(String src) {
|
||||
return doReplaceRegex(dtAreaR, src);
|
||||
}
|
||||
|
||||
public String getDetailMark() {
|
||||
return dtMark;
|
||||
}
|
||||
|
||||
public String getDetailMarkR(String src) {
|
||||
return doReplaceRegex(dtMarkR, src);
|
||||
}
|
||||
|
||||
public String getDetailActor() {
|
||||
return dtActor;
|
||||
}
|
||||
|
||||
public String getDetailActorR(String src) {
|
||||
return doReplaceRegex(dtActorR, src);
|
||||
}
|
||||
|
||||
public String getDetailDirector() {
|
||||
return dtDirector;
|
||||
}
|
||||
|
||||
public String getDetailDirectorR(String src) {
|
||||
return doReplaceRegex(dtDirectorR, src);
|
||||
}
|
||||
|
||||
public String getDetailDesc() {
|
||||
return dtDesc;
|
||||
}
|
||||
|
||||
public String getDetailDescR(String src) {
|
||||
return doReplaceRegex(dtDescR, src);
|
||||
}
|
||||
|
||||
public String getDetailFromNode() {
|
||||
return dtFromNode;
|
||||
}
|
||||
|
||||
public String getDetailFromName() {
|
||||
return dtFromName;
|
||||
}
|
||||
|
||||
public String getDetailFromNameR(String src) {
|
||||
return doReplaceRegex(dtFromNameR, src);
|
||||
}
|
||||
|
||||
public String getDetailUrlNode() {
|
||||
return dtUrlNode;
|
||||
}
|
||||
|
||||
public String getDetailUrlSubNode() {
|
||||
return dtUrlSubNode;
|
||||
}
|
||||
|
||||
public String getDetailUrlId() {
|
||||
return dtUrlId;
|
||||
}
|
||||
|
||||
public String getDetailUrlIdR(String src) {
|
||||
return doReplaceRegex(dtUrlIdR, src);
|
||||
}
|
||||
|
||||
public String getDetailUrlName() {
|
||||
return dtUrlName;
|
||||
}
|
||||
|
||||
public String getDetailUrlNameR(String src) {
|
||||
return doReplaceRegex(dtUrlNameR, src);
|
||||
}
|
||||
|
||||
public String getPlayUrl() {
|
||||
return playUrl;
|
||||
}
|
||||
|
||||
public String getPlayUa() {
|
||||
return playUa;
|
||||
}
|
||||
|
||||
public String getSearchUrl() {
|
||||
return searchUrl;
|
||||
}
|
||||
|
||||
public String getSearchVodNode() {
|
||||
return scVodNode;
|
||||
}
|
||||
|
||||
public String getSearchVodName() {
|
||||
return scVodName;
|
||||
}
|
||||
|
||||
public String getSearchVodNameR(String src) {
|
||||
return doReplaceRegex(scVodNameR, src);
|
||||
}
|
||||
|
||||
public String getSearchVodId() {
|
||||
return scVodId;
|
||||
}
|
||||
|
||||
public String getSearchVodIdR(String src) {
|
||||
return doReplaceRegex(scVodIdR, src);
|
||||
}
|
||||
|
||||
public String getSearchVodImg() {
|
||||
return scVodImg;
|
||||
}
|
||||
|
||||
public String getSearchVodImgR(String src) {
|
||||
return doReplaceRegex(scVodImgR, src);
|
||||
}
|
||||
|
||||
public String getSearchVodMark() {
|
||||
return scVodMark;
|
||||
}
|
||||
|
||||
public String getSearchVodMarkR(String src) {
|
||||
return doReplaceRegex(scVodMarkR, src);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue