pull/5/head
parent
f61af8d6d1
commit
71d38f1bc4
@ -0,0 +1,36 @@ |
|||||||
|
<component name="InspectionProjectProfileManager"> |
||||||
|
<profile version="1.0"> |
||||||
|
<option name="myName" value="Project Default" /> |
||||||
|
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true"> |
||||||
|
<option name="TOP_LEVEL_CLASS_OPTIONS"> |
||||||
|
<value> |
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
||||||
|
<option name="REQUIRED_TAGS" value="" /> |
||||||
|
</value> |
||||||
|
</option> |
||||||
|
<option name="INNER_CLASS_OPTIONS"> |
||||||
|
<value> |
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
||||||
|
<option name="REQUIRED_TAGS" value="" /> |
||||||
|
</value> |
||||||
|
</option> |
||||||
|
<option name="METHOD_OPTIONS"> |
||||||
|
<value> |
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" /> |
||||||
|
</value> |
||||||
|
</option> |
||||||
|
<option name="FIELD_OPTIONS"> |
||||||
|
<value> |
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> |
||||||
|
<option name="REQUIRED_TAGS" value="" /> |
||||||
|
</value> |
||||||
|
</option> |
||||||
|
<option name="IGNORE_DEPRECATED" value="false" /> |
||||||
|
<option name="IGNORE_JAVADOC_PERIOD" value="true" /> |
||||||
|
<option name="IGNORE_DUPLICATED_THROWS" value="false" /> |
||||||
|
<option name="IGNORE_POINT_TO_ITSELF" value="false" /> |
||||||
|
<option name="myAdditionalJavadocTags" value="date" /> |
||||||
|
</inspection_tool> |
||||||
|
</profile> |
||||||
|
</component> |
@ -0,0 +1,10 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="RunConfigurationProducerService"> |
||||||
|
<option name="ignoredProducers"> |
||||||
|
<set> |
||||||
|
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" /> |
||||||
|
</set> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
</project> |
@ -1,16 +0,0 @@ |
|||||||
package xyz.fycz.myreader.application; |
|
||||||
|
|
||||||
import java.security.cert.X509Certificate; |
|
||||||
|
|
||||||
import javax.net.ssl.X509TrustManager; |
|
||||||
|
|
||||||
public class TrustAllCerts implements X509TrustManager { |
|
||||||
@Override |
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType) {} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType) {} |
|
||||||
|
|
||||||
@Override |
|
||||||
public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} |
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package xyz.fycz.myreader.common; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class ErrorCode { |
|
||||||
|
|
||||||
public static final int login_not_user = 1; // 用户不存在
|
|
||||||
public static final int login_not_password = 2;// 密码错误
|
|
||||||
public static final int internet_waring = 3;// 网络访问错误
|
|
||||||
public static final int no_security = 4;// 没有权限(登陆过期)
|
|
||||||
public static final int no_login_ = 5;// 没有登录
|
|
||||||
public static final int meeting_user_no = 6;// 报名用户不存在
|
|
||||||
public static final int old_password = 8;// 原密码错误
|
|
||||||
public static final int execute_error = 7;//程序运行异常
|
|
||||||
public static final int order_timeout = 9;// 订餐超时
|
|
||||||
public static final int email_or_emailPwd_empty = 10;//邮箱或邮箱密码为空
|
|
||||||
public static final int email_login_error = 11;//邮箱登陆失败
|
|
||||||
public static final int email_params_error = 12;//邮箱接口参数不完整
|
|
||||||
public static final int suggestion_params_error = 13;//反馈意见接口参数不完整
|
|
||||||
public static final int email_addresses_error = 15;//邮箱地址无效
|
|
||||||
public static final int uploadfile_extend_error = 16;//上传附件后缀不支持
|
|
||||||
public static final int params_overlength = 17;//接口参数过长
|
|
||||||
public static final int leave_error = 18;//请假审批人跟请假人不能相同
|
|
||||||
public static final int login_simple_pwd = 19;//简单登录密码
|
|
||||||
|
|
||||||
|
|
||||||
public static final int more_depart = 1011;//多部门用户
|
|
||||||
public static final int Certificate_sys_no_user = 1012;//认证系统内无此用户
|
|
||||||
public static final int Certificate_no_bind_user = 1013;//用户没绑定证书在系统内
|
|
||||||
public static final int ukey_duplicate_user = 1014;//ukey序列号系统中不存在或存在多笔数据,请联系管理员
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,266 @@ |
|||||||
|
package xyz.fycz.myreader.entity.thirdsource; |
||||||
|
|
||||||
|
import com.google.gson.Gson; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import kotlin.jvm.Transient; |
||||||
|
|
||||||
|
// 解析阅读3.0的书源规则,toBookSourceBean()方法转换为阅读2.0书源规则
|
||||||
|
// https://raw.githubusercontent.com/gedoor/legado/master/app/src/main/java/io/legado/app/data/entities/BookSource.kt
|
||||||
|
public class BookSource3Bean { |
||||||
|
private String bookSourceName = ""; // 名称
|
||||||
|
private String bookSourceGroup; // 分组
|
||||||
|
private String bookSourceUrl = ""; // 地址,包括 http/https
|
||||||
|
private int bookSourceType = 0; // 类型,0 文本,1 音频
|
||||||
|
private String bookUrlPattern; // 详情页url正则
|
||||||
|
private int customOrder = 0; // 手动排序编号
|
||||||
|
private Boolean enabled = true; // 是否启用
|
||||||
|
private Boolean enabledExplore = true; // 启用发现
|
||||||
|
private String header; // 请求头
|
||||||
|
private String loginUrl; // 登录地址
|
||||||
|
private String bookSourceComment; // 注释
|
||||||
|
private Long lastUpdateTime = 0L; // 最后更新时间,用于排序
|
||||||
|
private int weight = 0; // 智能排序的权重
|
||||||
|
private String exploreUrl; // 发现url
|
||||||
|
private ExploreRule ruleExplore; // 发现规则
|
||||||
|
private String searchUrl; // 搜索url
|
||||||
|
private SearchRule ruleSearch; // 搜索规则
|
||||||
|
private BookInfoRule ruleBookInfo; // 书籍信息页规则
|
||||||
|
private TocRule ruleToc; // 目录页规则
|
||||||
|
private ContentRule ruleContent; // 正文页规则
|
||||||
|
|
||||||
|
@Transient |
||||||
|
private String userAgent; |
||||||
|
@Transient |
||||||
|
private String RuleSearchUrl; |
||||||
|
|
||||||
|
class ContentRule { |
||||||
|
String content; |
||||||
|
String nextContentUrl; |
||||||
|
String webJs; |
||||||
|
String sourceRegex; |
||||||
|
String replaceRegex; |
||||||
|
String imageStyle; //默认大小居中,FULL最大宽度
|
||||||
|
} |
||||||
|
|
||||||
|
class TocRule { |
||||||
|
String chapterList; |
||||||
|
String chapterName; |
||||||
|
String chapterUrl; |
||||||
|
String isVip; |
||||||
|
String updateTime; |
||||||
|
String nextTocUrl; |
||||||
|
} |
||||||
|
|
||||||
|
class BookInfoRule { |
||||||
|
String init; |
||||||
|
String name; |
||||||
|
String author; |
||||||
|
String intro; |
||||||
|
String kind; |
||||||
|
String lastChapter; |
||||||
|
String updateTime; |
||||||
|
String coverUrl; |
||||||
|
String tocUrl; |
||||||
|
String wordCount; |
||||||
|
} |
||||||
|
|
||||||
|
class SearchRule { |
||||||
|
String bookList; |
||||||
|
String name; |
||||||
|
String author; |
||||||
|
String intro; |
||||||
|
String kind; |
||||||
|
String lastChapter; |
||||||
|
String updateTime; |
||||||
|
String bookUrl; |
||||||
|
String coverUrl; |
||||||
|
String wordCount; |
||||||
|
} |
||||||
|
|
||||||
|
class ExploreRule { |
||||||
|
String bookList; |
||||||
|
String name; |
||||||
|
String author; |
||||||
|
String intro; |
||||||
|
String kind; |
||||||
|
String lastChapter; |
||||||
|
String updateTime; |
||||||
|
String bookUrl; |
||||||
|
String coverUrl; |
||||||
|
String wordCount; |
||||||
|
} |
||||||
|
|
||||||
|
/* @Override |
||||||
|
public Object clone() { |
||||||
|
try { |
||||||
|
Gson gson = new Gson(); |
||||||
|
String json = gson.toJson(this); |
||||||
|
return gson.fromJson(json, BookSource3Bean.class); |
||||||
|
} catch (Exception ignored) { |
||||||
|
} |
||||||
|
return this; |
||||||
|
}*/ |
||||||
|
|
||||||
|
// 给书源增加一个标签
|
||||||
|
public BookSource3Bean addGroupTag(String tag) { |
||||||
|
if (this.bookSourceGroup != null) { |
||||||
|
//为了避免空格、首尾位置的差异造成影响,这里做循环处理
|
||||||
|
String[] tags = (this.bookSourceGroup + ";" + tag).split(";"); |
||||||
|
|
||||||
|
List<String> list = new ArrayList<>(); |
||||||
|
list.add(tag); |
||||||
|
for (String s : tags) { |
||||||
|
if (!list.contains(s)) { |
||||||
|
list.add(s); |
||||||
|
} |
||||||
|
} |
||||||
|
bookSourceGroup = tag; |
||||||
|
for (int i = 1; i < list.size(); i++) { |
||||||
|
bookSourceGroup = bookSourceGroup + ";" + list.get(i); |
||||||
|
} |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
class httpRequest { |
||||||
|
String method; |
||||||
|
String body; |
||||||
|
String headers; |
||||||
|
String charset; |
||||||
|
} |
||||||
|
|
||||||
|
private String searchUrl2RuleSearchUrl(String searchUrl) { |
||||||
|
String RuleSearchUrl = searchUrl; |
||||||
|
if (searchUrl != null) { |
||||||
|
String q = ""; |
||||||
|
if (searchUrl.replaceAll("\\s", "").matches("^[^,]+,\\{.+\\}")) { |
||||||
|
// 正常网址不包含逗号
|
||||||
|
String[] strings = searchUrl.split(",", 2); |
||||||
|
try { |
||||||
|
Gson gson = new Gson(); |
||||||
|
httpRequest request = gson.fromJson(strings[1], httpRequest.class); |
||||||
|
if (gson.toJson(request).replaceAll("\\s", "").length() > 0) { |
||||||
|
// 阅读2.0没有单独的header,只有useragent
|
||||||
|
if (request.headers != null) { |
||||||
|
if (this.header == null) |
||||||
|
this.header = request.headers; |
||||||
|
else if (request.headers.trim().length() < 1) |
||||||
|
this.header = request.headers; |
||||||
|
} |
||||||
|
|
||||||
|
if (request.charset != null) { |
||||||
|
if (request.charset.trim().length() > 0) |
||||||
|
q = q + "|char=" + request.charset; |
||||||
|
} |
||||||
|
|
||||||
|
if (request.body != null) { |
||||||
|
q = request.body |
||||||
|
.replace("{{key}}", "searchKey") |
||||||
|
.replaceFirst("\\{\\{([^{}]*)page([^{}]*)\\}\\}", "$1searchPage$2") |
||||||
|
+ q; |
||||||
|
|
||||||
|
// post请求的关键词一定在第二部分
|
||||||
|
if (request.method != null) { |
||||||
|
if (request.method.toLowerCase().contains("post")) |
||||||
|
q = "@" + q; |
||||||
|
else |
||||||
|
q = "?" + q; |
||||||
|
} |
||||||
|
return strings[0] + q; |
||||||
|
} |
||||||
|
|
||||||
|
RuleSearchUrl = strings[0] + q; |
||||||
|
} else |
||||||
|
RuleSearchUrl = searchUrl; |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
RuleSearchUrl = searchUrl; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return RuleSearchUrl.replaceAll("\\s", "") |
||||||
|
.replace("{{key}}", "searchKey") |
||||||
|
.replaceFirst("\\{\\{([^{}]*)page([^{}]*)\\}\\}", "$1searchPage$2") |
||||||
|
; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public BookSourceBean toBookSourceBean() { |
||||||
|
// 带注释的行,表示2.0/3.0书源json的数据命名不同。注释后方为2.0名称
|
||||||
|
String bookSourceType = ""; |
||||||
|
if (this.bookSourceType != 0) |
||||||
|
bookSourceType = "" + this.bookSourceType; |
||||||
|
|
||||||
|
RuleSearchUrl = searchUrl2RuleSearchUrl(searchUrl); |
||||||
|
|
||||||
|
if (header != null && userAgent == null) { |
||||||
|
if (header.matches("(?!).*(User-Agent).*")) |
||||||
|
userAgent = header.replaceFirst("(?!).*(User-Agent)[\\s:]+\"([^\"]+)\".*", "$2"); |
||||||
|
} |
||||||
|
|
||||||
|
String ruleFindUrl=null; |
||||||
|
if(exploreUrl!=null){ |
||||||
|
ruleFindUrl=exploreUrl.replaceAll("\\{\\{page\\}\\}","searchPage"); |
||||||
|
} |
||||||
|
|
||||||
|
// 暂时只给发现和搜索添加了header
|
||||||
|
String header=""; |
||||||
|
if(this.header!=null){ |
||||||
|
if(this.header.trim().length()>0) |
||||||
|
header="@Header:"+this.header.replaceAll("\\n"," "); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return new BookSourceBean( |
||||||
|
bookSourceUrl, |
||||||
|
bookSourceName, |
||||||
|
bookSourceGroup, |
||||||
|
bookSourceType, |
||||||
|
loginUrl, |
||||||
|
lastUpdateTime, |
||||||
|
0, //u serialNumber,
|
||||||
|
weight, |
||||||
|
true, //u enable,
|
||||||
|
ruleFindUrl+header,//发现规则 ruleFindUrl,
|
||||||
|
ruleExplore.bookList, // 列表 ruleFindList,
|
||||||
|
ruleExplore.name,// ruleFindName,
|
||||||
|
ruleExplore.author,// ruleFindAuthor,
|
||||||
|
ruleExplore.kind,// ruleFindKind,
|
||||||
|
ruleExplore.intro,// ruleFindIntroduce,
|
||||||
|
ruleExplore.lastChapter,// ruleFindLastChapter,
|
||||||
|
ruleExplore.coverUrl,// ruleFindCoverUrl,
|
||||||
|
ruleExplore.bookUrl,//??? ruleFindNoteUrl,
|
||||||
|
RuleSearchUrl+header,// ruleSearchUrl,
|
||||||
|
ruleSearch.bookList,// ruleSearchList,
|
||||||
|
ruleSearch.name,// ruleSearchName,
|
||||||
|
ruleSearch.author,// ruleSearchAuthor,
|
||||||
|
ruleSearch.kind,// ruleSearchKind,
|
||||||
|
ruleSearch.intro,// ruleSearchIntroduce,
|
||||||
|
ruleSearch.lastChapter,// ruleSearchLastChapter,
|
||||||
|
ruleSearch.coverUrl,//ruleSearchCoverUrl,
|
||||||
|
ruleSearch.bookUrl,// ruleSearchNoteUrl,
|
||||||
|
bookUrlPattern, //??? ruleBookUrlPattern,
|
||||||
|
ruleBookInfo.init,// ruleBookInfoInit,
|
||||||
|
ruleBookInfo.name,// ruleBookName,
|
||||||
|
ruleBookInfo.author,// ruleBookAuthor,
|
||||||
|
ruleBookInfo.coverUrl,// ruleCoverUrl,
|
||||||
|
ruleBookInfo.intro,// ruleIntroduce,
|
||||||
|
ruleBookInfo.kind,// ruleBookKind,
|
||||||
|
ruleBookInfo.lastChapter,// ruleBookLastChapter,
|
||||||
|
ruleBookInfo.tocUrl,// ruleChapterUrl,
|
||||||
|
ruleToc.nextTocUrl,// ruleChapterUrlNext,
|
||||||
|
ruleToc.chapterList,// ruleChapterList,
|
||||||
|
ruleToc.chapterName,// ruleChapterName,
|
||||||
|
ruleToc.chapterUrl, // ruleContentUrl,
|
||||||
|
ruleContent.nextContentUrl, //ruleContentUrlNext,
|
||||||
|
ruleContent.content, // ruleBookContent,
|
||||||
|
ruleContent.replaceRegex,// ruleBookContentReplace,
|
||||||
|
userAgent // httpUserAgent
|
||||||
|
); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,709 @@ |
|||||||
|
package xyz.fycz.myreader.entity.thirdsource; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import com.google.gson.Gson; |
||||||
|
|
||||||
|
import org.greenrobot.greendao.annotation.Entity; |
||||||
|
import org.greenrobot.greendao.annotation.Generated; |
||||||
|
import org.greenrobot.greendao.annotation.Id; |
||||||
|
import org.greenrobot.greendao.annotation.NotNull; |
||||||
|
import org.greenrobot.greendao.annotation.OrderBy; |
||||||
|
import org.greenrobot.greendao.annotation.Transient; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.util.utils.StringUtils; |
||||||
|
|
||||||
|
import static android.text.TextUtils.isEmpty; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by GKF on 2017/12/14. |
||||||
|
* 书源信息 |
||||||
|
*/ |
||||||
|
@Entity |
||||||
|
public class BookSourceBean implements Cloneable { |
||||||
|
@Id |
||||||
|
private String bookSourceUrl; |
||||||
|
private String bookSourceName; |
||||||
|
private String bookSourceGroup; |
||||||
|
private String bookSourceType; |
||||||
|
private String loginUrl; |
||||||
|
private Long lastUpdateTime; |
||||||
|
@OrderBy |
||||||
|
private int serialNumber; |
||||||
|
@OrderBy |
||||||
|
@NotNull |
||||||
|
private int weight = 0; |
||||||
|
private boolean enable; |
||||||
|
//发现规则
|
||||||
|
private String ruleFindUrl; |
||||||
|
private String ruleFindList; |
||||||
|
private String ruleFindName; |
||||||
|
private String ruleFindAuthor; |
||||||
|
private String ruleFindKind; |
||||||
|
private String ruleFindIntroduce; |
||||||
|
private String ruleFindLastChapter; |
||||||
|
private String ruleFindCoverUrl; |
||||||
|
private String ruleFindNoteUrl; |
||||||
|
//搜索规则
|
||||||
|
private String ruleSearchUrl; |
||||||
|
private String ruleSearchList; |
||||||
|
private String ruleSearchName; |
||||||
|
private String ruleSearchAuthor; |
||||||
|
private String ruleSearchKind; |
||||||
|
private String ruleSearchIntroduce; |
||||||
|
private String ruleSearchLastChapter; |
||||||
|
private String ruleSearchCoverUrl; |
||||||
|
private String ruleSearchNoteUrl; |
||||||
|
//详情页规则
|
||||||
|
private String ruleBookUrlPattern; |
||||||
|
private String ruleBookInfoInit; |
||||||
|
private String ruleBookName; |
||||||
|
private String ruleBookAuthor; |
||||||
|
private String ruleCoverUrl; |
||||||
|
private String ruleIntroduce; |
||||||
|
private String ruleBookKind; |
||||||
|
private String ruleBookLastChapter; |
||||||
|
private String ruleChapterUrl; |
||||||
|
//目录页规则
|
||||||
|
private String ruleChapterUrlNext; |
||||||
|
private String ruleChapterList; |
||||||
|
private String ruleChapterName; |
||||||
|
private String ruleContentUrl; |
||||||
|
//正文页规则
|
||||||
|
private String ruleContentUrlNext; |
||||||
|
private String ruleBookContent; |
||||||
|
private String ruleBookContentReplace; |
||||||
|
private String httpUserAgent; |
||||||
|
|
||||||
|
@Transient |
||||||
|
private transient ArrayList<String> groupList; |
||||||
|
|
||||||
|
@Generated(hash = 243497779) |
||||||
|
public BookSourceBean(String bookSourceUrl, String bookSourceName, String bookSourceGroup, String bookSourceType, String loginUrl, Long lastUpdateTime, int serialNumber, int weight, boolean enable, String ruleFindUrl, String ruleFindList, |
||||||
|
String ruleFindName, String ruleFindAuthor, String ruleFindKind, String ruleFindIntroduce, String ruleFindLastChapter, String ruleFindCoverUrl, String ruleFindNoteUrl, String ruleSearchUrl, String ruleSearchList, |
||||||
|
String ruleSearchName, String ruleSearchAuthor, String ruleSearchKind, String ruleSearchIntroduce, String ruleSearchLastChapter, String ruleSearchCoverUrl, String ruleSearchNoteUrl, String ruleBookUrlPattern, |
||||||
|
String ruleBookInfoInit, String ruleBookName, String ruleBookAuthor, String ruleCoverUrl, String ruleIntroduce, String ruleBookKind, String ruleBookLastChapter, String ruleChapterUrl, String ruleChapterUrlNext, |
||||||
|
String ruleChapterList, String ruleChapterName, String ruleContentUrl, String ruleContentUrlNext, String ruleBookContent, String ruleBookContentReplace, String httpUserAgent) { |
||||||
|
this.bookSourceUrl = bookSourceUrl; |
||||||
|
this.bookSourceName = bookSourceName; |
||||||
|
this.bookSourceGroup = bookSourceGroup; |
||||||
|
this.bookSourceType = bookSourceType; |
||||||
|
this.loginUrl = loginUrl; |
||||||
|
this.lastUpdateTime = lastUpdateTime; |
||||||
|
this.serialNumber = serialNumber; |
||||||
|
this.weight = weight; |
||||||
|
this.enable = enable; |
||||||
|
this.ruleFindUrl = ruleFindUrl; |
||||||
|
this.ruleFindList = ruleFindList; |
||||||
|
this.ruleFindName = ruleFindName; |
||||||
|
this.ruleFindAuthor = ruleFindAuthor; |
||||||
|
this.ruleFindKind = ruleFindKind; |
||||||
|
this.ruleFindIntroduce = ruleFindIntroduce; |
||||||
|
this.ruleFindLastChapter = ruleFindLastChapter; |
||||||
|
this.ruleFindCoverUrl = ruleFindCoverUrl; |
||||||
|
this.ruleFindNoteUrl = ruleFindNoteUrl; |
||||||
|
this.ruleSearchUrl = ruleSearchUrl; |
||||||
|
this.ruleSearchList = ruleSearchList; |
||||||
|
this.ruleSearchName = ruleSearchName; |
||||||
|
this.ruleSearchAuthor = ruleSearchAuthor; |
||||||
|
this.ruleSearchKind = ruleSearchKind; |
||||||
|
this.ruleSearchIntroduce = ruleSearchIntroduce; |
||||||
|
this.ruleSearchLastChapter = ruleSearchLastChapter; |
||||||
|
this.ruleSearchCoverUrl = ruleSearchCoverUrl; |
||||||
|
this.ruleSearchNoteUrl = ruleSearchNoteUrl; |
||||||
|
this.ruleBookUrlPattern = ruleBookUrlPattern; |
||||||
|
this.ruleBookInfoInit = ruleBookInfoInit; |
||||||
|
this.ruleBookName = ruleBookName; |
||||||
|
this.ruleBookAuthor = ruleBookAuthor; |
||||||
|
this.ruleCoverUrl = ruleCoverUrl; |
||||||
|
this.ruleIntroduce = ruleIntroduce; |
||||||
|
this.ruleBookKind = ruleBookKind; |
||||||
|
this.ruleBookLastChapter = ruleBookLastChapter; |
||||||
|
this.ruleChapterUrl = ruleChapterUrl; |
||||||
|
this.ruleChapterUrlNext = ruleChapterUrlNext; |
||||||
|
this.ruleChapterList = ruleChapterList; |
||||||
|
this.ruleChapterName = ruleChapterName; |
||||||
|
this.ruleContentUrl = ruleContentUrl; |
||||||
|
this.ruleContentUrlNext = ruleContentUrlNext; |
||||||
|
this.ruleBookContent = ruleBookContent; |
||||||
|
this.ruleBookContentReplace = ruleBookContentReplace; |
||||||
|
this.httpUserAgent = httpUserAgent; |
||||||
|
} |
||||||
|
|
||||||
|
public BookSourceBean(BookSourceBean sourceBean) { |
||||||
|
this.bookSourceUrl = sourceBean.bookSourceUrl; |
||||||
|
this.bookSourceName = sourceBean.bookSourceName; |
||||||
|
this.bookSourceGroup = sourceBean.bookSourceGroup; |
||||||
|
this.bookSourceType = sourceBean.bookSourceType; |
||||||
|
this.loginUrl = sourceBean.loginUrl; |
||||||
|
this.lastUpdateTime = sourceBean.lastUpdateTime; |
||||||
|
this.serialNumber = sourceBean.serialNumber; |
||||||
|
this.weight = sourceBean.weight; |
||||||
|
this.enable = sourceBean.enable; |
||||||
|
this.ruleFindUrl = sourceBean.ruleFindUrl; |
||||||
|
this.ruleFindList = sourceBean.ruleFindList; |
||||||
|
this.ruleFindName = sourceBean.ruleFindName; |
||||||
|
this.ruleFindAuthor = sourceBean.ruleFindAuthor; |
||||||
|
this.ruleFindKind = sourceBean.ruleFindKind; |
||||||
|
this.ruleFindIntroduce = sourceBean.ruleFindIntroduce; |
||||||
|
this.ruleFindLastChapter = sourceBean.ruleFindLastChapter; |
||||||
|
this.ruleFindCoverUrl = sourceBean.ruleFindCoverUrl; |
||||||
|
this.ruleFindNoteUrl = sourceBean.ruleFindNoteUrl; |
||||||
|
this.ruleSearchUrl = sourceBean.ruleSearchUrl; |
||||||
|
this.ruleSearchList = sourceBean.ruleSearchList; |
||||||
|
this.ruleSearchName = sourceBean.ruleSearchName; |
||||||
|
this.ruleSearchAuthor = sourceBean.ruleSearchAuthor; |
||||||
|
this.ruleSearchKind = sourceBean.ruleSearchKind; |
||||||
|
this.ruleSearchIntroduce = sourceBean.ruleSearchIntroduce; |
||||||
|
this.ruleSearchLastChapter = sourceBean.ruleSearchLastChapter; |
||||||
|
this.ruleSearchCoverUrl = sourceBean.ruleSearchCoverUrl; |
||||||
|
this.ruleSearchNoteUrl = sourceBean.ruleSearchNoteUrl; |
||||||
|
this.ruleBookUrlPattern = sourceBean.ruleBookUrlPattern; |
||||||
|
this.ruleBookInfoInit = sourceBean.ruleBookInfoInit; |
||||||
|
this.ruleBookName = sourceBean.ruleBookName; |
||||||
|
this.ruleBookAuthor = sourceBean.ruleBookAuthor; |
||||||
|
this.ruleCoverUrl = sourceBean.ruleCoverUrl; |
||||||
|
this.ruleIntroduce = sourceBean.ruleIntroduce; |
||||||
|
this.ruleBookKind = sourceBean.ruleBookKind; |
||||||
|
this.ruleBookLastChapter = sourceBean.ruleBookLastChapter; |
||||||
|
this.ruleChapterUrl = sourceBean.ruleChapterUrl; |
||||||
|
this.ruleChapterUrlNext = sourceBean.ruleChapterUrlNext; |
||||||
|
this.ruleChapterList = sourceBean.ruleChapterList; |
||||||
|
this.ruleChapterName = sourceBean.ruleChapterName; |
||||||
|
this.ruleContentUrl = sourceBean.ruleContentUrl; |
||||||
|
this.ruleContentUrlNext = sourceBean.ruleContentUrlNext; |
||||||
|
this.ruleBookContent = sourceBean.ruleBookContent; |
||||||
|
this.ruleBookContentReplace = sourceBean.ruleBookContentReplace; |
||||||
|
this.httpUserAgent = sourceBean.httpUserAgent; |
||||||
|
} |
||||||
|
|
||||||
|
public BookSourceBean() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) { |
||||||
|
if (obj instanceof BookSourceBean) { |
||||||
|
BookSourceBean bs = (BookSourceBean) obj; |
||||||
|
return stringEquals(bookSourceUrl, bs.bookSourceUrl) |
||||||
|
&& stringEquals(bookSourceName, bs.bookSourceName) |
||||||
|
&& stringEquals(bookSourceType, bs.bookSourceType) |
||||||
|
&& stringEquals(loginUrl, bs.loginUrl) |
||||||
|
&& stringEquals(bookSourceGroup, bs.bookSourceGroup) |
||||||
|
&& stringEquals(ruleBookName, bs.ruleBookName) |
||||||
|
&& stringEquals(ruleBookAuthor, bs.ruleBookAuthor) |
||||||
|
&& stringEquals(ruleChapterUrl, bs.ruleChapterUrl) |
||||||
|
&& stringEquals(ruleChapterUrlNext, ruleChapterUrlNext) |
||||||
|
&& stringEquals(ruleCoverUrl, bs.ruleCoverUrl) |
||||||
|
&& stringEquals(ruleIntroduce, bs.ruleIntroduce) |
||||||
|
&& stringEquals(ruleChapterList, bs.ruleChapterList) |
||||||
|
&& stringEquals(ruleChapterName, bs.ruleChapterName) |
||||||
|
&& stringEquals(ruleContentUrl, bs.ruleContentUrl) |
||||||
|
&& stringEquals(ruleContentUrlNext, bs.ruleContentUrlNext) |
||||||
|
&& stringEquals(ruleBookContent, bs.ruleBookContent) |
||||||
|
&& stringEquals(ruleSearchUrl, bs.ruleSearchUrl) |
||||||
|
&& stringEquals(ruleSearchList, bs.ruleSearchList) |
||||||
|
&& stringEquals(ruleSearchName, bs.ruleSearchName) |
||||||
|
&& stringEquals(ruleSearchAuthor, bs.ruleSearchAuthor) |
||||||
|
&& stringEquals(ruleSearchKind, bs.ruleSearchKind) |
||||||
|
&& stringEquals(ruleSearchLastChapter, bs.ruleSearchLastChapter) |
||||||
|
&& stringEquals(ruleSearchCoverUrl, bs.ruleSearchCoverUrl) |
||||||
|
&& stringEquals(ruleSearchNoteUrl, bs.ruleSearchNoteUrl) |
||||||
|
&& stringEquals(httpUserAgent, bs.httpUserAgent) |
||||||
|
&& stringEquals(ruleBookKind, bs.ruleBookKind) |
||||||
|
&& stringEquals(ruleBookLastChapter, bs.ruleBookLastChapter) |
||||||
|
&& stringEquals(ruleBookUrlPattern, bs.ruleBookUrlPattern) |
||||||
|
&& stringEquals(ruleBookContentReplace, bs.ruleBookContentReplace); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private Boolean stringEquals(String str1, String str2) { |
||||||
|
return Objects.equals(str1, str2) || (isEmpty(str1) && isEmpty(str2)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() { |
||||||
|
try { |
||||||
|
Gson gson = new Gson(); |
||||||
|
String json = gson.toJson(this); |
||||||
|
return gson.fromJson(json, BookSourceBean.class); |
||||||
|
} catch (Exception ignored) { |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getBookSourceName() { |
||||||
|
return bookSourceName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBookSourceName(String bookSourceName) { |
||||||
|
this.bookSourceName = bookSourceName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getBookSourceUrl() { |
||||||
|
return bookSourceUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBookSourceUrl(String bookSourceUrl) { |
||||||
|
this.bookSourceUrl = bookSourceUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public int getSerialNumber() { |
||||||
|
return this.serialNumber; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSerialNumber(int serialNumber) { |
||||||
|
this.serialNumber = serialNumber; |
||||||
|
} |
||||||
|
|
||||||
|
public int getWeight() { |
||||||
|
return this.weight; |
||||||
|
} |
||||||
|
|
||||||
|
public void setWeight(int weight) { |
||||||
|
this.weight = weight; |
||||||
|
} |
||||||
|
|
||||||
|
// 换源时选择的源权重+500
|
||||||
|
public void increaseWeightBySelection() { |
||||||
|
this.weight += 500; |
||||||
|
} |
||||||
|
|
||||||
|
public void increaseWeight(int increase) { |
||||||
|
this.weight += increase; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean getEnable() { |
||||||
|
return this.enable; |
||||||
|
} |
||||||
|
|
||||||
|
public void setEnable(boolean enable) { |
||||||
|
this.enable = enable; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookName() { |
||||||
|
return this.ruleBookName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookName(String ruleBookName) { |
||||||
|
this.ruleBookName = ruleBookName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookAuthor() { |
||||||
|
return this.ruleBookAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookAuthor(String ruleBookAuthor) { |
||||||
|
this.ruleBookAuthor = ruleBookAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleChapterUrl() { |
||||||
|
return this.ruleChapterUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleChapterUrl(String ruleChapterUrl) { |
||||||
|
this.ruleChapterUrl = ruleChapterUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleCoverUrl() { |
||||||
|
return this.ruleCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleCoverUrl(String ruleCoverUrl) { |
||||||
|
this.ruleCoverUrl = ruleCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleIntroduce() { |
||||||
|
return this.ruleIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleIntroduce(String ruleIntroduce) { |
||||||
|
this.ruleIntroduce = ruleIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookContent() { |
||||||
|
return this.ruleBookContent; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookContent(String ruleBookContent) { |
||||||
|
this.ruleBookContent = ruleBookContent; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchUrl() { |
||||||
|
return this.ruleSearchUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchUrl(String ruleSearchUrl) { |
||||||
|
this.ruleSearchUrl = ruleSearchUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleContentUrl() { |
||||||
|
return this.ruleContentUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleContentUrl(String ruleContentUrl) { |
||||||
|
this.ruleContentUrl = ruleContentUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchName() { |
||||||
|
return this.ruleSearchName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchName(String ruleSearchName) { |
||||||
|
this.ruleSearchName = ruleSearchName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchAuthor() { |
||||||
|
return this.ruleSearchAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchAuthor(String ruleSearchAuthor) { |
||||||
|
this.ruleSearchAuthor = ruleSearchAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchKind() { |
||||||
|
return this.ruleSearchKind; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchKind(String ruleSearchKind) { |
||||||
|
this.ruleSearchKind = ruleSearchKind; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchLastChapter() { |
||||||
|
return this.ruleSearchLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchLastChapter(String ruleSearchLastChapter) { |
||||||
|
this.ruleSearchLastChapter = ruleSearchLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchCoverUrl() { |
||||||
|
return this.ruleSearchCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchCoverUrl(String ruleSearchCoverUrl) { |
||||||
|
this.ruleSearchCoverUrl = ruleSearchCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchNoteUrl() { |
||||||
|
return this.ruleSearchNoteUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchNoteUrl(String ruleSearchNoteUrl) { |
||||||
|
this.ruleSearchNoteUrl = ruleSearchNoteUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchList() { |
||||||
|
return this.ruleSearchList; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchList(String ruleSearchList) { |
||||||
|
this.ruleSearchList = ruleSearchList; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleChapterList() { |
||||||
|
return this.ruleChapterList; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleChapterList(String ruleChapterList) { |
||||||
|
this.ruleChapterList = ruleChapterList; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleChapterName() { |
||||||
|
return this.ruleChapterName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleChapterName(String ruleChapterName) { |
||||||
|
this.ruleChapterName = ruleChapterName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getHttpUserAgent() { |
||||||
|
return this.httpUserAgent; |
||||||
|
} |
||||||
|
|
||||||
|
public void setHttpUserAgent(String httpHeaders) { |
||||||
|
this.httpUserAgent = httpHeaders; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindUrl() { |
||||||
|
return this.ruleFindUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindUrl(String ruleFindUrl) { |
||||||
|
this.ruleFindUrl = ruleFindUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getBookSourceGroup() { |
||||||
|
return this.bookSourceGroup; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBookSourceGroup(String bookSourceGroup) { |
||||||
|
this.bookSourceGroup = bookSourceGroup; |
||||||
|
upGroupList(); |
||||||
|
this.bookSourceGroup = TextUtils.join("; ", groupList); |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleChapterUrlNext() { |
||||||
|
return this.ruleChapterUrlNext; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleChapterUrlNext(String ruleChapterUrlNext) { |
||||||
|
this.ruleChapterUrlNext = ruleChapterUrlNext; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleContentUrlNext() { |
||||||
|
return this.ruleContentUrlNext; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleContentUrlNext(String ruleContentUrlNext) { |
||||||
|
this.ruleContentUrlNext = ruleContentUrlNext; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookUrlPattern() { |
||||||
|
return ruleBookUrlPattern; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookUrlPattern(String ruleBookUrlPattern) { |
||||||
|
this.ruleBookUrlPattern = ruleBookUrlPattern; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookKind() { |
||||||
|
return ruleBookKind; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookKind(String ruleBookKind) { |
||||||
|
this.ruleBookKind = ruleBookKind; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookLastChapter() { |
||||||
|
return ruleBookLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookLastChapter(String ruleBookLastChapter) { |
||||||
|
this.ruleBookLastChapter = ruleBookLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
private void upGroupList() { |
||||||
|
if (groupList == null) |
||||||
|
groupList = new ArrayList<>(); |
||||||
|
else |
||||||
|
groupList.clear(); |
||||||
|
if (!TextUtils.isEmpty(bookSourceGroup)) { |
||||||
|
for (String group : bookSourceGroup.split("\\s*[,;,;]\\s*")) { |
||||||
|
group = group.trim(); |
||||||
|
if (TextUtils.isEmpty(group) || groupList.contains(group)) continue; |
||||||
|
groupList.add(group); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void addGroup(String group) { |
||||||
|
if (groupList == null) |
||||||
|
upGroupList(); |
||||||
|
if (!groupList.contains(group)) { |
||||||
|
groupList.add(group); |
||||||
|
updateModTime(); |
||||||
|
bookSourceGroup = TextUtils.join("; ", groupList); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void removeGroup(String group) { |
||||||
|
if (groupList == null) |
||||||
|
upGroupList(); |
||||||
|
if (groupList.contains(group)) { |
||||||
|
groupList.remove(group); |
||||||
|
updateModTime(); |
||||||
|
bookSourceGroup = TextUtils.join("; ", groupList); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean containsGroup(String group) { |
||||||
|
if (groupList == null) { |
||||||
|
upGroupList(); |
||||||
|
} |
||||||
|
return groupList.contains(group); |
||||||
|
} |
||||||
|
|
||||||
|
public Long getLastUpdateTime() { |
||||||
|
return lastUpdateTime; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLastUpdateTime(Long lastUpdateTime) { |
||||||
|
this.lastUpdateTime = lastUpdateTime; |
||||||
|
} |
||||||
|
|
||||||
|
public void updateModTime() { |
||||||
|
this.lastUpdateTime = System.currentTimeMillis(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getLoginUrl() { |
||||||
|
return this.loginUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLoginUrl(String loginUrl) { |
||||||
|
this.loginUrl = loginUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getBookSourceType() { |
||||||
|
return bookSourceType == null ? "" : bookSourceType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBookSourceType(String bookSourceType) { |
||||||
|
this.bookSourceType = bookSourceType; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleSearchIntroduce() { |
||||||
|
return this.ruleSearchIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleSearchIntroduce(String ruleSearchIntroduce) { |
||||||
|
this.ruleSearchIntroduce = ruleSearchIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindList() { |
||||||
|
return this.ruleFindList; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindList(String ruleFindList) { |
||||||
|
this.ruleFindList = ruleFindList; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindName() { |
||||||
|
return this.ruleFindName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindName(String ruleFindName) { |
||||||
|
this.ruleFindName = ruleFindName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindAuthor() { |
||||||
|
return this.ruleFindAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindAuthor(String ruleFindAuthor) { |
||||||
|
this.ruleFindAuthor = ruleFindAuthor; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindKind() { |
||||||
|
return this.ruleFindKind; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindKind(String ruleFindKind) { |
||||||
|
this.ruleFindKind = ruleFindKind; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindIntroduce() { |
||||||
|
return this.ruleFindIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindIntroduce(String ruleFindIntroduce) { |
||||||
|
this.ruleFindIntroduce = ruleFindIntroduce; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindLastChapter() { |
||||||
|
return this.ruleFindLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindLastChapter(String ruleFindLastChapter) { |
||||||
|
this.ruleFindLastChapter = ruleFindLastChapter; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindCoverUrl() { |
||||||
|
return this.ruleFindCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindCoverUrl(String ruleFindCoverUrl) { |
||||||
|
this.ruleFindCoverUrl = ruleFindCoverUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleFindNoteUrl() { |
||||||
|
return this.ruleFindNoteUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleFindNoteUrl(String ruleFindNoteUrl) { |
||||||
|
this.ruleFindNoteUrl = ruleFindNoteUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookInfoInit() { |
||||||
|
return this.ruleBookInfoInit; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookInfoInit(String ruleBookInfoInit) { |
||||||
|
this.ruleBookInfoInit = ruleBookInfoInit; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRuleBookContentReplace() { |
||||||
|
return ruleBookContentReplace; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRuleBookContentReplace(String ruleBookContentReplace) { |
||||||
|
this.ruleBookContentReplace = ruleBookContentReplace; |
||||||
|
} |
||||||
|
|
||||||
|
public String getJson(int maxLength) { |
||||||
|
try { |
||||||
|
String source = getMinJson(false); |
||||||
|
// 优先直接输出
|
||||||
|
if (source.getBytes("utf-8").length <= maxLength) |
||||||
|
return source; |
||||||
|
source = StringUtils.zipString(source |
||||||
|
.replaceFirst("^\\{", "") |
||||||
|
// 保留末位的括号,用于解压缩后的验证
|
||||||
|
.replaceFirst("(\\s|\n)*\\}$", "}") |
||||||
|
.trim()); |
||||||
|
// 优先输出带发现的书源
|
||||||
|
if (source.getBytes("utf-8").length < maxLength) |
||||||
|
return "{" + source; |
||||||
|
// 去除发现
|
||||||
|
return "{" + StringUtils.zipString(getMinJson(true) |
||||||
|
.replaceFirst("^\\{", "") |
||||||
|
// 保留末位的括号,用于解压缩后的验证
|
||||||
|
.replaceFirst("(\\s|\n)*\\}$", "}") |
||||||
|
.trim()); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 把书源bean转为json,并去除不必要的信息。 |
||||||
|
* |
||||||
|
* @param removeFind false,去除空信息和排序、可用性信息。true,额外去除发现规则 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public String getMinJson(Boolean removeFind) { |
||||||
|
BookSourceBean bean = new BookSourceBean(this); |
||||||
|
String json; |
||||||
|
|
||||||
|
if (removeFind) { |
||||||
|
bean.setRuleFindUrl(null); |
||||||
|
bean.setRuleFindList(null); |
||||||
|
bean.setRuleFindName(null); |
||||||
|
bean.setRuleFindAuthor(null); |
||||||
|
bean.setRuleFindKind(null); |
||||||
|
bean.setRuleFindIntroduce(null); |
||||||
|
bean.setRuleFindLastChapter(null); |
||||||
|
bean.setRuleFindCoverUrl(null); |
||||||
|
bean.setRuleFindNoteUrl(null); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
Gson gson = new Gson(); |
||||||
|
json = gson.toJson(bean); |
||||||
|
|
||||||
|
return json.replaceFirst("\n\\s*\"enable\":\\s*\\S+(,)?\\s*", "\n") |
||||||
|
.replaceFirst("\n\\s*\"serialNumber\":\\s*\\d+(,)?\\s*", "\n") |
||||||
|
.replaceFirst("\n\\s*\"\"weight\":\\s*\\d+(,)?\\s*", "\n") |
||||||
|
.replaceAll("\n\\s*\"[a-zA-Z]+\"(:\"\"|: \"\"| :\"\"| : \"\")\\s*,\\s*\n", "\n") |
||||||
|
.replaceAll("\\s*\n\\s*", "") |
||||||
|
; |
||||||
|
} catch (Exception ignored) { |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,205 @@ |
|||||||
|
package xyz.fycz.myreader.model.analyzeRule; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.JsonPath; |
||||||
|
import com.jayway.jsonpath.ReadContext; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
public class AnalyzeByJSonPath { |
||||||
|
private static final Pattern jsonRulePattern = Pattern.compile("(?<=\\{)\\$\\..+?(?=\\})"); |
||||||
|
private ReadContext ctx; |
||||||
|
|
||||||
|
public AnalyzeByJSonPath parse(Object json) { |
||||||
|
if (json instanceof String) { |
||||||
|
ctx = JsonPath.parse((String) json); |
||||||
|
} else { |
||||||
|
ctx = JsonPath.parse(json); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getString(String rule) { |
||||||
|
if (TextUtils.isEmpty(rule)) return null; |
||||||
|
String result = ""; |
||||||
|
String[] rules; |
||||||
|
String elementsType; |
||||||
|
|
||||||
|
if (rule.contains("{$.")) { |
||||||
|
result = rule; |
||||||
|
Matcher matcher = jsonRulePattern.matcher(rule); |
||||||
|
while (matcher.find()) { |
||||||
|
result = result.replace(String.format("{%s}", matcher.group()), getString(matcher.group().trim())); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
if (rule.contains("&&")) { |
||||||
|
rules = rule.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else { |
||||||
|
rules = rule.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
|
||||||
|
if (rules.length == 1) { |
||||||
|
try { |
||||||
|
Object object = ctx.read(rule); |
||||||
|
if (object instanceof List) { |
||||||
|
StringBuilder builder = new StringBuilder(); |
||||||
|
for (Object o : (List) object) { |
||||||
|
builder.append(o).append("\n"); |
||||||
|
} |
||||||
|
result = builder.toString().replaceAll("\\n$", ""); |
||||||
|
} else { |
||||||
|
result = String.valueOf(object); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
if (!rule.startsWith("$.")) { |
||||||
|
return rule; |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
List<String> textS = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
String temp = getString(rl); |
||||||
|
if (!TextUtils.isEmpty(temp)) { |
||||||
|
textS.add(temp); |
||||||
|
if (elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return TextUtils.join(",", textS).trim(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
List<String> getStringList(String rule) { |
||||||
|
List<String> result = new ArrayList<>(); |
||||||
|
if (TextUtils.isEmpty(rule)) return result; |
||||||
|
String[] rules; |
||||||
|
String elementsType; |
||||||
|
if (rule.contains("&&")) { |
||||||
|
rules = rule.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else if (rule.contains("%%")) { |
||||||
|
rules = rule.split("%%"); |
||||||
|
elementsType = "%"; |
||||||
|
} else { |
||||||
|
rules = rule.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
if (rules.length == 1) { |
||||||
|
if (!rule.contains("{$.")) { |
||||||
|
try { |
||||||
|
Object object = ctx.read(rule); |
||||||
|
if (object == null) return result; |
||||||
|
if (object instanceof List) { |
||||||
|
for (Object o : ((List) object)) |
||||||
|
result.add(String.valueOf(o)); |
||||||
|
} else { |
||||||
|
result.add(String.valueOf(object)); |
||||||
|
} |
||||||
|
} catch (Exception ignored) { |
||||||
|
} |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
Matcher matcher = jsonRulePattern.matcher(rule); |
||||||
|
while (matcher.find()) { |
||||||
|
List<String> stringList = getStringList(matcher.group()); |
||||||
|
for (String s : stringList) { |
||||||
|
result.add(rule.replace(String.format("{%s}", matcher.group()), s)); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} else { |
||||||
|
List<List<String>> results = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
List<String> temp = getStringList(rl); |
||||||
|
if (temp != null && !temp.isEmpty()) { |
||||||
|
results.add(temp); |
||||||
|
if (temp.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < results.get(0).size(); i++) { |
||||||
|
for (List<String> temp : results) { |
||||||
|
if (i < temp.size()) { |
||||||
|
result.add(temp.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (List<String> temp : results) { |
||||||
|
result.addAll(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Object getObject(String rule) { |
||||||
|
return ctx.read(rule); |
||||||
|
} |
||||||
|
|
||||||
|
List<Object> getList(String rule) { |
||||||
|
List<Object> result = new ArrayList<>(); |
||||||
|
if (TextUtils.isEmpty(rule)) return result; |
||||||
|
String elementsType; |
||||||
|
String[] rules; |
||||||
|
if (rule.contains("&&")) { |
||||||
|
rules = rule.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else if (rule.contains("%%")) { |
||||||
|
rules = rule.split("%%"); |
||||||
|
elementsType = "%"; |
||||||
|
} else { |
||||||
|
rules = rule.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
if (rules.length == 1) { |
||||||
|
try { |
||||||
|
return ctx.read(rules[0]); |
||||||
|
} catch (Exception e) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} else { |
||||||
|
List<List> results = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
List temp = getList(rl); |
||||||
|
if (temp != null && !temp.isEmpty()) { |
||||||
|
results.add(temp); |
||||||
|
if (temp.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < results.get(0).size(); i++) { |
||||||
|
for (List temp : results) { |
||||||
|
if (i < temp.size()) { |
||||||
|
result.add(temp.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (List temp : results) { |
||||||
|
result.addAll(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,454 @@ |
|||||||
|
package xyz.fycz.myreader.model.analyzeRule; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import org.jsoup.Jsoup; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.nodes.TextNode; |
||||||
|
import org.jsoup.select.Collector; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
import org.jsoup.select.Evaluator; |
||||||
|
import org.seimicrawler.xpath.JXNode; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.util.utils.StringUtils; |
||||||
|
|
||||||
|
import static android.text.TextUtils.isEmpty; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by GKF on 2018/1/25. |
||||||
|
* 书源规则解析 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class AnalyzeByJSoup { |
||||||
|
private Element element; |
||||||
|
|
||||||
|
public AnalyzeByJSoup parse(Object doc) { |
||||||
|
if (doc instanceof Element) { |
||||||
|
element = (Element) doc; |
||||||
|
} else if (doc instanceof JXNode) { |
||||||
|
JXNode jxNode = (JXNode) doc; |
||||||
|
if (jxNode.isElement()) { |
||||||
|
element = jxNode.asElement(); |
||||||
|
} else { |
||||||
|
element = Jsoup.parse(jxNode.value().toString()); |
||||||
|
} |
||||||
|
} else { |
||||||
|
element = Jsoup.parse(doc.toString()); |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取列表 |
||||||
|
*/ |
||||||
|
Elements getElements(String rule) { |
||||||
|
return getElements(element, rule); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 合并内容列表,得到内容 |
||||||
|
*/ |
||||||
|
String getString(String ruleStr) { |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
List<String> textS = getStringList(ruleStr); |
||||||
|
if (textS.size() == 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return TextUtils.join(",", textS).trim(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取一个字符串 |
||||||
|
**/ |
||||||
|
String getString0(String ruleStr) { |
||||||
|
List<String> urlList = getStringList(ruleStr); |
||||||
|
if (!urlList.isEmpty()) { |
||||||
|
return urlList.get(0); |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有内容列表 |
||||||
|
*/ |
||||||
|
List<String> getStringList(String ruleStr) { |
||||||
|
List<String> textS = new ArrayList<>(); |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return textS; |
||||||
|
} |
||||||
|
//拆分规则
|
||||||
|
SourceRule sourceRule = new SourceRule(ruleStr); |
||||||
|
if (isEmpty(sourceRule.elementsRule)) { |
||||||
|
textS.add(element.data()); |
||||||
|
} else { |
||||||
|
String elementsType; |
||||||
|
String[] ruleStrS; |
||||||
|
if (sourceRule.elementsRule.contains("&")) { |
||||||
|
elementsType = "&"; |
||||||
|
ruleStrS = sourceRule.elementsRule.split("&+"); |
||||||
|
} else if (sourceRule.elementsRule.contains("%%")) { |
||||||
|
elementsType = "%"; |
||||||
|
ruleStrS = sourceRule.elementsRule.split("%%"); |
||||||
|
} else { |
||||||
|
elementsType = "|"; |
||||||
|
if (sourceRule.isCss) { |
||||||
|
ruleStrS = sourceRule.elementsRule.split("\\|\\|"); |
||||||
|
} else { |
||||||
|
ruleStrS = sourceRule.elementsRule.split("\\|+"); |
||||||
|
} |
||||||
|
} |
||||||
|
List<List<String>> results = new ArrayList<>(); |
||||||
|
for (String ruleStrX : ruleStrS) { |
||||||
|
List<String> temp; |
||||||
|
if (sourceRule.isCss) { |
||||||
|
int lastIndex = ruleStrX.lastIndexOf('@'); |
||||||
|
temp = getResultLast(element.select(ruleStrX.substring(0, lastIndex)), ruleStrX.substring(lastIndex + 1)); |
||||||
|
} else { |
||||||
|
temp = getResultList(ruleStrX); |
||||||
|
} |
||||||
|
if (temp != null && !temp.isEmpty()) { |
||||||
|
results.add(temp); |
||||||
|
if (!results.isEmpty() && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < results.get(0).size(); i++) { |
||||||
|
for (List<String> temp : results) { |
||||||
|
if (i < temp.size()) { |
||||||
|
textS.add(temp.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (List<String> temp : results) { |
||||||
|
textS.addAll(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isEmpty(sourceRule.replaceRegex)) { |
||||||
|
List<String> tempList = new ArrayList<>(textS); |
||||||
|
textS.clear(); |
||||||
|
for (String text : tempList) { |
||||||
|
text = text.replaceAll(sourceRule.replaceRegex, sourceRule.replacement); |
||||||
|
if (text.length() > 0) { |
||||||
|
textS.add(text); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return textS; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取Elements |
||||||
|
*/ |
||||||
|
private Elements getElements(Element temp, String rule) { |
||||||
|
Elements elements = new Elements(); |
||||||
|
if (temp == null || isEmpty(rule)) { |
||||||
|
return elements; |
||||||
|
} |
||||||
|
SourceRule sourceRule = new SourceRule(rule); |
||||||
|
String elementsType; |
||||||
|
String[] ruleStrS; |
||||||
|
if (sourceRule.elementsRule.contains("&")) { |
||||||
|
elementsType = "&"; |
||||||
|
ruleStrS = sourceRule.elementsRule.split("&+"); |
||||||
|
} else if (sourceRule.elementsRule.contains("%")) { |
||||||
|
elementsType = "%"; |
||||||
|
ruleStrS = sourceRule.elementsRule.split("%+"); |
||||||
|
} else { |
||||||
|
elementsType = "|"; |
||||||
|
if (sourceRule.isCss) { |
||||||
|
ruleStrS = sourceRule.elementsRule.split("\\|\\|"); |
||||||
|
} else { |
||||||
|
ruleStrS = sourceRule.elementsRule.split("\\|+"); |
||||||
|
} |
||||||
|
} |
||||||
|
List<Elements> elementsList = new ArrayList<>(); |
||||||
|
if (sourceRule.isCss) { |
||||||
|
for (String ruleStr : ruleStrS) { |
||||||
|
Elements tempS = temp.select(ruleStr); |
||||||
|
elementsList.add(tempS); |
||||||
|
if (tempS.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (String ruleStr : ruleStrS) { |
||||||
|
Elements tempS = getElementsSingle(temp, ruleStr); |
||||||
|
elementsList.add(tempS); |
||||||
|
if (tempS.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (elementsList.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < elementsList.get(0).size(); i++) { |
||||||
|
for (Elements es : elementsList) { |
||||||
|
if (i < es.size()) { |
||||||
|
elements.add(es.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (Elements es : elementsList) { |
||||||
|
elements.addAll(es); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return elements; |
||||||
|
} |
||||||
|
|
||||||
|
private Elements filterElements(Elements elements, String[] rules) { |
||||||
|
if (rules == null || rules.length < 2) return elements; |
||||||
|
Elements selectedEls = new Elements(); |
||||||
|
for (Element ele : elements) { |
||||||
|
boolean isOk = false; |
||||||
|
switch (rules[0]) { |
||||||
|
case "class": |
||||||
|
isOk = ele.getElementsByClass(rules[1]).size() > 0; |
||||||
|
break; |
||||||
|
case "id": |
||||||
|
isOk = ele.getElementById(rules[1]) != null; |
||||||
|
break; |
||||||
|
case "tag": |
||||||
|
isOk = ele.getElementsByTag(rules[1]).size() > 0; |
||||||
|
break; |
||||||
|
case "text": |
||||||
|
isOk = ele.getElementsContainingOwnText(rules[1]).size() > 0; |
||||||
|
break; |
||||||
|
} |
||||||
|
if (isOk) { |
||||||
|
selectedEls.add(ele); |
||||||
|
} |
||||||
|
} |
||||||
|
return selectedEls; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取Elements按照一个规则 |
||||||
|
*/ |
||||||
|
private Elements getElementsSingle(Element temp, String rule) { |
||||||
|
Elements elements = new Elements(); |
||||||
|
try { |
||||||
|
String[] rs = rule.trim().split("@"); |
||||||
|
if (rs.length > 1) { |
||||||
|
elements.add(temp); |
||||||
|
for (String rl : rs) { |
||||||
|
Elements es = new Elements(); |
||||||
|
for (Element et : elements) { |
||||||
|
es.addAll(getElements(et, rl)); |
||||||
|
} |
||||||
|
elements.clear(); |
||||||
|
elements.addAll(es); |
||||||
|
} |
||||||
|
} else { |
||||||
|
String[] rulePcx = rule.split("!"); |
||||||
|
String[] rulePc = rulePcx[0].trim().split(">"); |
||||||
|
String[] rules = rulePc[0].trim().split("\\."); |
||||||
|
String[] filterRules = null; |
||||||
|
boolean needFilterElements = rulePc.length > 1 && !isEmpty(rulePc[1].trim()); |
||||||
|
if (needFilterElements) { |
||||||
|
filterRules = rulePc[1].trim().split("\\."); |
||||||
|
filterRules[0] = filterRules[0].trim(); |
||||||
|
List<String> validKeys = Arrays.asList("class", "id", "tag", "text"); |
||||||
|
if (filterRules.length < 2 || !validKeys.contains(filterRules[0]) || isEmpty(filterRules[1].trim())) { |
||||||
|
needFilterElements = false; |
||||||
|
} |
||||||
|
filterRules[1] = filterRules[1].trim(); |
||||||
|
} |
||||||
|
switch (rules[0]) { |
||||||
|
case "children": |
||||||
|
Elements children = temp.children(); |
||||||
|
if (needFilterElements) |
||||||
|
children = filterElements(children, filterRules); |
||||||
|
elements.addAll(children); |
||||||
|
break; |
||||||
|
case "class": |
||||||
|
Elements elementsByClass = temp.getElementsByClass(rules[1]); |
||||||
|
if (rules.length == 3) { |
||||||
|
int index = Integer.parseInt(rules[2]); |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsByClass.get(elementsByClass.size() + index)); |
||||||
|
} else { |
||||||
|
elements.add(elementsByClass.get(index)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsByClass = filterElements(elementsByClass, filterRules); |
||||||
|
elements.addAll(elementsByClass); |
||||||
|
} |
||||||
|
break; |
||||||
|
case "tag": |
||||||
|
Elements elementsByTag = temp.getElementsByTag(rules[1]); |
||||||
|
if (rules.length == 3) { |
||||||
|
int index = Integer.parseInt(rules[2]); |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsByTag.get(elementsByTag.size() + index)); |
||||||
|
} else { |
||||||
|
elements.add(elementsByTag.get(index)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsByTag = filterElements(elementsByTag, filterRules); |
||||||
|
elements.addAll(elementsByTag); |
||||||
|
} |
||||||
|
break; |
||||||
|
case "id": |
||||||
|
Elements elementsById = Collector.collect(new Evaluator.Id(rules[1]), temp); |
||||||
|
if (rules.length == 3) { |
||||||
|
int index = Integer.parseInt(rules[2]); |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsById.get(elementsById.size() + index)); |
||||||
|
} else { |
||||||
|
elements.add(elementsById.get(index)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsById = filterElements(elementsById, filterRules); |
||||||
|
elements.addAll(elementsById); |
||||||
|
} |
||||||
|
break; |
||||||
|
case "text": |
||||||
|
Elements elementsByText = temp.getElementsContainingOwnText(rules[1]); |
||||||
|
if (needFilterElements) |
||||||
|
elementsByText = filterElements(elementsByText, filterRules); |
||||||
|
elements.addAll(elementsByText); |
||||||
|
break; |
||||||
|
default: |
||||||
|
elements.addAll(temp.select(rulePcx[0])); |
||||||
|
} |
||||||
|
if (rulePcx.length > 1) { |
||||||
|
String[] rulePcs = rulePcx[1].split(":"); |
||||||
|
for (String pc : rulePcs) { |
||||||
|
int pcInt = Integer.parseInt(pc); |
||||||
|
if (pcInt < 0 && elements.size() + pcInt >= 0) { |
||||||
|
elements.set(elements.size() + pcInt, null); |
||||||
|
} else if (Integer.parseInt(pc) < elements.size()) { |
||||||
|
elements.set(Integer.parseInt(pc), null); |
||||||
|
} |
||||||
|
} |
||||||
|
Elements es = new Elements(); |
||||||
|
es.add(null); |
||||||
|
elements.removeAll(es); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception ignore) { |
||||||
|
} |
||||||
|
return elements; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取内容列表 |
||||||
|
*/ |
||||||
|
private List<String> getResultList(String ruleStr) { |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Elements elements = new Elements(); |
||||||
|
elements.add(element); |
||||||
|
String[] rules = ruleStr.split("@"); |
||||||
|
for (int i = 0; i < rules.length - 1; i++) { |
||||||
|
Elements es = new Elements(); |
||||||
|
for (Element elt : elements) { |
||||||
|
es.addAll(getElementsSingle(elt, rules[i])); |
||||||
|
} |
||||||
|
elements.clear(); |
||||||
|
elements = es; |
||||||
|
} |
||||||
|
if (elements.isEmpty()) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return getResultLast(elements, rules[rules.length - 1]); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据最后一个规则获取内容 |
||||||
|
*/ |
||||||
|
private List<String> getResultLast(Elements elements, String lastRule) { |
||||||
|
List<String> textS = new ArrayList<>(); |
||||||
|
List<String> cText = new ArrayList<>(); |
||||||
|
try { |
||||||
|
switch (lastRule) { |
||||||
|
case "text": |
||||||
|
for (Element element : elements) { |
||||||
|
String text = element.text(); |
||||||
|
cText.add(text); |
||||||
|
} |
||||||
|
textS.add(TextUtils.join("\n", cText)); |
||||||
|
break; |
||||||
|
case "textNodes": |
||||||
|
for (Element element : elements) { |
||||||
|
List<TextNode> contentEs = element.textNodes(); |
||||||
|
for (int i = 0; i < contentEs.size(); i++) { |
||||||
|
String temp = contentEs.get(i).text().trim(); |
||||||
|
if (!isEmpty(temp)) { |
||||||
|
cText.add(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
textS.add(TextUtils.join("\n", cText)); |
||||||
|
break; |
||||||
|
case "ownText": |
||||||
|
for (Element element : elements) { |
||||||
|
cText.add(element.ownText()); |
||||||
|
} |
||||||
|
textS.add(TextUtils.join("\n", cText)); |
||||||
|
break; |
||||||
|
case "html": |
||||||
|
elements.select("script, style").remove(); |
||||||
|
String html = elements.html(); |
||||||
|
textS.add(html); |
||||||
|
break; |
||||||
|
case "all": |
||||||
|
textS.add(elements.outerHtml()); |
||||||
|
break; |
||||||
|
default: |
||||||
|
for (Element element : elements) { |
||||||
|
String url = element.attr(lastRule); |
||||||
|
if (!TextUtils.isEmpty(url) && !textS.contains(url)) { |
||||||
|
textS.add(url); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception ignore) { |
||||||
|
} |
||||||
|
return textS; |
||||||
|
} |
||||||
|
|
||||||
|
class SourceRule { |
||||||
|
boolean isCss = false; |
||||||
|
String elementsRule; |
||||||
|
String replaceRegex = ""; |
||||||
|
String replacement = ""; |
||||||
|
|
||||||
|
SourceRule(String ruleStr) { |
||||||
|
if (StringUtils.startWithIgnoreCase(ruleStr, "@CSS:")) { |
||||||
|
isCss = true; |
||||||
|
elementsRule = ruleStr.substring(5).trim(); |
||||||
|
return; |
||||||
|
} |
||||||
|
String[] ruleStrS; |
||||||
|
//分离正则表达式
|
||||||
|
ruleStrS = ruleStr.trim().split("#"); |
||||||
|
elementsRule = ruleStrS[0]; |
||||||
|
if (ruleStrS.length > 1) { |
||||||
|
replaceRegex = ruleStrS[1]; |
||||||
|
} |
||||||
|
if (ruleStrS.length > 2) { |
||||||
|
replacement = ruleStrS[2]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,194 @@ |
|||||||
|
package xyz.fycz.myreader.model.analyzeRule; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import org.jsoup.nodes.Document; |
||||||
|
import org.jsoup.nodes.Element; |
||||||
|
import org.jsoup.select.Elements; |
||||||
|
import org.seimicrawler.xpath.JXDocument; |
||||||
|
import org.seimicrawler.xpath.JXNode; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class AnalyzeByXPath { |
||||||
|
private JXDocument jxDocument; |
||||||
|
private JXNode jxNode; |
||||||
|
|
||||||
|
public AnalyzeByXPath parse(Object doc) { |
||||||
|
if (doc instanceof JXNode) { |
||||||
|
jxNode = (JXNode) doc; |
||||||
|
if (!jxNode.isElement()) { |
||||||
|
jxDocument = strToJXDocument(doc.toString()); |
||||||
|
jxNode = null; |
||||||
|
} |
||||||
|
} else if (doc instanceof Document) { |
||||||
|
jxDocument = JXDocument.create((Document) doc); |
||||||
|
jxNode = null; |
||||||
|
} else if (doc instanceof Element) { |
||||||
|
jxDocument = JXDocument.create(new Elements((Element) doc)); |
||||||
|
jxNode = null; |
||||||
|
} else if (doc instanceof Elements) { |
||||||
|
jxDocument = JXDocument.create((Elements) doc); |
||||||
|
jxNode = null; |
||||||
|
} else { |
||||||
|
jxDocument = strToJXDocument(doc.toString()); |
||||||
|
jxNode = null; |
||||||
|
} |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
private JXDocument strToJXDocument(String html) { |
||||||
|
if (html.endsWith("</td>")) { |
||||||
|
html = String.format("<tr>%s</tr>", html); |
||||||
|
} |
||||||
|
if (html.endsWith("</tr>") || html.endsWith("</tbody>")) { |
||||||
|
html = String.format("<table>%s</table>", html); |
||||||
|
} |
||||||
|
return JXDocument.create(html); |
||||||
|
} |
||||||
|
|
||||||
|
List<JXNode> getElements(String xPath) { |
||||||
|
if (TextUtils.isEmpty(xPath)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
List<JXNode> jxNodes = new ArrayList<>(); |
||||||
|
String elementsType; |
||||||
|
String[] rules; |
||||||
|
if (xPath.contains("&&")) { |
||||||
|
rules = xPath.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else if (xPath.contains("%%")) { |
||||||
|
rules = xPath.split("%%"); |
||||||
|
elementsType = "%"; |
||||||
|
} else { |
||||||
|
rules = xPath.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
if (rules.length == 1) { |
||||||
|
if (jxNode != null) { |
||||||
|
return jxNode.sel(rules[0]); |
||||||
|
} |
||||||
|
return jxDocument.selN(rules[0]); |
||||||
|
} else { |
||||||
|
List<List<JXNode>> results = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
List<JXNode> temp = getElements(rl); |
||||||
|
if (temp != null && !temp.isEmpty()) { |
||||||
|
results.add(temp); |
||||||
|
if (temp.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < results.get(0).size(); i++) { |
||||||
|
for (List<JXNode> temp : results) { |
||||||
|
if (i < temp.size()) { |
||||||
|
jxNodes.add(temp.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (List<JXNode> temp : results) { |
||||||
|
jxNodes.addAll(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return jxNodes; |
||||||
|
} |
||||||
|
|
||||||
|
List<String> getStringList(String xPath) { |
||||||
|
List<String> result = new ArrayList<>(); |
||||||
|
String elementsType; |
||||||
|
String[] rules; |
||||||
|
if (xPath.contains("&&")) { |
||||||
|
rules = xPath.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else if (xPath.contains("%%")) { |
||||||
|
rules = xPath.split("%%"); |
||||||
|
elementsType = "%"; |
||||||
|
} else { |
||||||
|
rules = xPath.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
if (rules.length == 1) { |
||||||
|
List<JXNode> jxNodes; |
||||||
|
if (jxNode != null) { |
||||||
|
jxNodes = jxNode.sel(xPath); |
||||||
|
} else { |
||||||
|
jxNodes = jxDocument.selN(xPath); |
||||||
|
} |
||||||
|
for (JXNode jxNode : jxNodes) { |
||||||
|
/*if(jxNode.isString()){ |
||||||
|
result.add(String.valueOf(jxNode)); |
||||||
|
}*/ |
||||||
|
result.add(String.valueOf(jxNode)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
List<List<String>> results = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
List<String> temp = getStringList(rl); |
||||||
|
if (temp != null && !temp.isEmpty()) { |
||||||
|
results.add(temp); |
||||||
|
if (temp.size() > 0 && elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size() > 0) { |
||||||
|
if ("%".equals(elementsType)) { |
||||||
|
for (int i = 0; i < results.get(0).size(); i++) { |
||||||
|
for (List<String> temp : results) { |
||||||
|
if (i < temp.size()) { |
||||||
|
result.add(temp.get(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (List<String> temp : results) { |
||||||
|
result.addAll(temp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public String getString(String rule) { |
||||||
|
String[] rules; |
||||||
|
String elementsType; |
||||||
|
if (rule.contains("&&")) { |
||||||
|
rules = rule.split("&&"); |
||||||
|
elementsType = "&"; |
||||||
|
} else { |
||||||
|
rules = rule.split("\\|\\|"); |
||||||
|
elementsType = "|"; |
||||||
|
} |
||||||
|
if (rules.length == 1) { |
||||||
|
List<JXNode> jxNodes; |
||||||
|
if (jxNode != null) { |
||||||
|
jxNodes = jxNode.sel(rule); |
||||||
|
} else { |
||||||
|
jxNodes = jxDocument.selN(rule); |
||||||
|
} |
||||||
|
if (jxNodes == null) return null; |
||||||
|
return TextUtils.join(",", jxNodes); |
||||||
|
} else { |
||||||
|
List<String> textS = new ArrayList<>(); |
||||||
|
for (String rl : rules) { |
||||||
|
String temp = getString(rl); |
||||||
|
if (!TextUtils.isEmpty(temp)) { |
||||||
|
textS.add(temp); |
||||||
|
if (elementsType.equals("|")) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return TextUtils.join(",", textS).trim(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,540 @@ |
|||||||
|
package xyz.fycz.myreader.model.analyzeRule; |
||||||
|
|
||||||
|
import android.annotation.SuppressLint; |
||||||
|
|
||||||
|
import androidx.annotation.Keep; |
||||||
|
|
||||||
|
import com.google.gson.Gson; |
||||||
|
|
||||||
|
import org.jsoup.nodes.Entities; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import javax.script.SimpleBindings; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.util.StringHelper; |
||||||
|
import xyz.fycz.myreader.util.utils.JsExtensions; |
||||||
|
import xyz.fycz.myreader.util.utils.NetworkUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.StringUtils; |
||||||
|
|
||||||
|
import static android.text.TextUtils.isEmpty; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.EXP_PATTERN; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.JS_PATTERN; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.MAP_STRING; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.SCRIPT_ENGINE; |
||||||
|
import static xyz.fycz.myreader.util.utils.NetworkUtils.headerPattern; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Created by REFGD. |
||||||
|
* 统一解析接口 |
||||||
|
*/ |
||||||
|
@Keep |
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"}) |
||||||
|
public class AnalyzeRule implements JsExtensions { |
||||||
|
/*private static final Pattern putPattern = Pattern.compile("@put:(\\{[^}]+?\\})", Pattern.CASE_INSENSITIVE); |
||||||
|
private static final Pattern getPattern = Pattern.compile("@get:\\{([^}]+?)\\}", Pattern.CASE_INSENSITIVE); |
||||||
|
|
||||||
|
private BaseBookBean book; |
||||||
|
private Object object; |
||||||
|
private Boolean isJSON = false; |
||||||
|
private String baseUrl = null; |
||||||
|
|
||||||
|
private AnalyzeByXPath analyzeByXPath = null; |
||||||
|
private AnalyzeByJSoup analyzeByJSoup = null; |
||||||
|
private AnalyzeByJSonPath analyzeByJSonPath = null; |
||||||
|
|
||||||
|
private boolean objectChangedXP = false; |
||||||
|
private boolean objectChangedJS = false; |
||||||
|
private boolean objectChangedJP = false; |
||||||
|
|
||||||
|
public AnalyzeRule(BaseBookBean bookBean) { |
||||||
|
book = bookBean; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBook(BaseBookBean book) { |
||||||
|
this.book = book; |
||||||
|
} |
||||||
|
|
||||||
|
public AnalyzeRule setContent(Object body) { |
||||||
|
return setContent(body, baseUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public Object getContent() { |
||||||
|
return object; |
||||||
|
} |
||||||
|
|
||||||
|
public AnalyzeRule setContent(Object body, String baseUrl) { |
||||||
|
if (body == null) throw new AssertionError("Content cannot be null"); |
||||||
|
isJSON = StringUtils.isJsonType(String.valueOf(body)); |
||||||
|
object = body; |
||||||
|
if (baseUrl != null) { |
||||||
|
this.baseUrl = headerPattern.matcher(baseUrl).replaceAll(""); |
||||||
|
} |
||||||
|
objectChangedXP = true; |
||||||
|
objectChangedJS = true; |
||||||
|
objectChangedJP = true; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public String getBaseUrl() { |
||||||
|
return this.baseUrl; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取XPath解析类 |
||||||
|
*//*
|
||||||
|
private AnalyzeByXPath getAnalyzeByXPath(Object o) { |
||||||
|
if (o != object) { |
||||||
|
return new AnalyzeByXPath().parse(o); |
||||||
|
} |
||||||
|
return getAnalyzeByXPath(); |
||||||
|
} |
||||||
|
|
||||||
|
private AnalyzeByXPath getAnalyzeByXPath() { |
||||||
|
if (analyzeByXPath == null || objectChangedXP) { |
||||||
|
analyzeByXPath = new AnalyzeByXPath(); |
||||||
|
analyzeByXPath.parse(object); |
||||||
|
objectChangedXP = false; |
||||||
|
} |
||||||
|
return analyzeByXPath; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取JSOUP解析类 |
||||||
|
*//*
|
||||||
|
private AnalyzeByJSoup getAnalyzeByJSoup(Object o) { |
||||||
|
if (o != object) { |
||||||
|
return new AnalyzeByJSoup().parse(o); |
||||||
|
} |
||||||
|
return getAnalyzeByJSoup(); |
||||||
|
} |
||||||
|
|
||||||
|
private AnalyzeByJSoup getAnalyzeByJSoup() { |
||||||
|
if (analyzeByJSoup == null || objectChangedJS) { |
||||||
|
analyzeByJSoup = new AnalyzeByJSoup(); |
||||||
|
analyzeByJSoup.parse(object); |
||||||
|
objectChangedJS = false; |
||||||
|
} |
||||||
|
return analyzeByJSoup; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取JSON解析类 |
||||||
|
*//*
|
||||||
|
private AnalyzeByJSonPath getAnalyzeByJSonPath(Object o) { |
||||||
|
if (o != object) { |
||||||
|
return new AnalyzeByJSonPath().parse(o); |
||||||
|
} |
||||||
|
return getAnalyzeByJSonPath(); |
||||||
|
} |
||||||
|
|
||||||
|
private AnalyzeByJSonPath getAnalyzeByJSonPath() { |
||||||
|
if (analyzeByJSonPath == null || objectChangedJP) { |
||||||
|
analyzeByJSonPath = new AnalyzeByJSonPath(); |
||||||
|
analyzeByJSonPath.parse(object); |
||||||
|
objectChangedJP = false; |
||||||
|
} |
||||||
|
return analyzeByJSonPath; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取文本列表 |
||||||
|
*//*
|
||||||
|
public List<String> getStringList(String rule) throws Exception { |
||||||
|
return getStringList(rule, false); |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> getStringList(String rule, boolean isUrl) throws Exception { |
||||||
|
if (isEmpty(rule)) return null; |
||||||
|
List<SourceRule> ruleList = splitSourceRule(rule); |
||||||
|
return getStringList(ruleList, isUrl); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"}) |
||||||
|
public List<String> getStringList(List<SourceRule> ruleList, boolean isUrl) throws Exception { |
||||||
|
Object result = null; |
||||||
|
if (!ruleList.isEmpty()) result = object; |
||||||
|
for (SourceRule rule : ruleList) { |
||||||
|
if (!isEmpty(rule.rule)) { |
||||||
|
switch (rule.mode) { |
||||||
|
case Js: |
||||||
|
result = evalJS(rule.rule, result); |
||||||
|
break; |
||||||
|
case JSon: |
||||||
|
result = getAnalyzeByJSonPath(result).getStringList(rule.rule); |
||||||
|
break; |
||||||
|
case XPath: |
||||||
|
result = getAnalyzeByXPath(result).getStringList(rule.rule); |
||||||
|
break; |
||||||
|
default: |
||||||
|
result = getAnalyzeByJSoup(result).getStringList(rule.rule); |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isEmpty(rule.replaceRegex) && result instanceof List) { |
||||||
|
List<String> newList = new ArrayList<>(); |
||||||
|
//noinspection rawtypes
|
||||||
|
for (Object item : (List) result) { |
||||||
|
newList.add(replaceRegex(String.valueOf(item), rule)); |
||||||
|
} |
||||||
|
result = newList; |
||||||
|
} else if (!isEmpty(rule.replaceRegex)) { |
||||||
|
result = replaceRegex(String.valueOf(result), rule); |
||||||
|
} |
||||||
|
} |
||||||
|
if (result == null) return new ArrayList<>(); |
||||||
|
if (result instanceof String) { |
||||||
|
result = Arrays.asList(StringUtils.formatHtml((String) result).split("\n")); |
||||||
|
} |
||||||
|
if (isUrl && !isEmpty(baseUrl)) { |
||||||
|
List<String> urlList = new ArrayList<>(); |
||||||
|
//noinspection rawtypes
|
||||||
|
for (Object url : (List) result) { |
||||||
|
String absoluteURL = NetworkUtils.getAbsoluteURL(baseUrl, String.valueOf(url)); |
||||||
|
if (!urlList.contains(absoluteURL) && !isEmpty(absoluteURL)) { |
||||||
|
urlList.add(absoluteURL); |
||||||
|
} |
||||||
|
} |
||||||
|
return urlList; |
||||||
|
} |
||||||
|
return (List<String>) result; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取文本 |
||||||
|
*//*
|
||||||
|
public String getString(String rule) throws Exception { |
||||||
|
return getString(rule, false); |
||||||
|
} |
||||||
|
|
||||||
|
public String getString(String ruleStr, boolean isUrl) throws Exception { |
||||||
|
if (isEmpty(ruleStr)) return null; |
||||||
|
List<SourceRule> ruleList = splitSourceRule(ruleStr); |
||||||
|
return getString(ruleList, isUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getString(List<SourceRule> ruleList) throws Exception { |
||||||
|
return getString(ruleList, false); |
||||||
|
} |
||||||
|
|
||||||
|
public String getString(List<SourceRule> ruleList, boolean isUrl) throws Exception { |
||||||
|
Object result = null; |
||||||
|
if (!ruleList.isEmpty()) result = object; |
||||||
|
for (SourceRule rule : ruleList) { |
||||||
|
if (!StringHelper.isEmpty(rule.rule)) { |
||||||
|
switch (rule.mode) { |
||||||
|
case Js: |
||||||
|
result = evalJS(rule.rule, result); |
||||||
|
break; |
||||||
|
case JSon: |
||||||
|
result = getAnalyzeByJSonPath(result).getString(rule.rule); |
||||||
|
break; |
||||||
|
case XPath: |
||||||
|
result = getAnalyzeByXPath(result).getString(rule.rule); |
||||||
|
break; |
||||||
|
case Default: |
||||||
|
if (isUrl && !isEmpty(baseUrl)) { |
||||||
|
result = getAnalyzeByJSoup(result).getString0(rule.rule); |
||||||
|
} else { |
||||||
|
result = getAnalyzeByJSoup(result).getString(rule.rule); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isEmpty(rule.replaceRegex)) { |
||||||
|
result = replaceRegex(String.valueOf(result), rule); |
||||||
|
} |
||||||
|
} |
||||||
|
if (result == null) return ""; |
||||||
|
if (isUrl && !StringHelper.isEmpty(baseUrl)) { |
||||||
|
return NetworkUtils.getAbsoluteURL(baseUrl, Entities.unescape(String.valueOf(result))); |
||||||
|
} |
||||||
|
try { |
||||||
|
return Entities.unescape(String.valueOf(result)); |
||||||
|
} catch (Exception e) { |
||||||
|
return String.valueOf(result); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取Element |
||||||
|
*//*
|
||||||
|
public Object getElement(String ruleStr) throws Exception { |
||||||
|
List<SourceRule> ruleList = splitSourceRule(ruleStr); |
||||||
|
Object result = object; |
||||||
|
for (SourceRule rule : ruleList) { |
||||||
|
switch (rule.mode) { |
||||||
|
case Js: |
||||||
|
result = evalJS(rule.rule, result); |
||||||
|
break; |
||||||
|
case JSon: |
||||||
|
result = getAnalyzeByJSonPath(result).getObject(rule.rule); |
||||||
|
break; |
||||||
|
case XPath: |
||||||
|
result = getAnalyzeByXPath(result).getElements(rule.rule); |
||||||
|
break; |
||||||
|
default: |
||||||
|
result = getAnalyzeByJSoup(result).getElements(rule.rule); |
||||||
|
} |
||||||
|
if (!isEmpty(rule.replaceRegex) && result instanceof String) { |
||||||
|
result = replaceRegex(String.valueOf(result), rule); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 获取列表 |
||||||
|
*//*
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
public List<Object> getElements(String ruleStr) throws Exception { |
||||||
|
List<SourceRule> ruleList = splitSourceRule(ruleStr); |
||||||
|
Object result = null; |
||||||
|
if (!ruleList.isEmpty()) result = object; |
||||||
|
for (SourceRule rule : ruleList) { |
||||||
|
switch (rule.mode) { |
||||||
|
case Js: |
||||||
|
result = evalJS(rule.rule, result); |
||||||
|
break; |
||||||
|
case JSon: |
||||||
|
result = getAnalyzeByJSonPath(result).getList(rule.rule); |
||||||
|
break; |
||||||
|
case XPath: |
||||||
|
result = getAnalyzeByXPath(result).getElements(rule.rule); |
||||||
|
break; |
||||||
|
default: |
||||||
|
result = getAnalyzeByJSoup(result).getElements(rule.rule); |
||||||
|
} |
||||||
|
if (!isEmpty(rule.replaceRegex) && result instanceof String) { |
||||||
|
result = replaceRegex(String.valueOf(result), rule); |
||||||
|
} |
||||||
|
} |
||||||
|
if (result == null) { |
||||||
|
return new ArrayList<>(); |
||||||
|
} |
||||||
|
return (List<Object>) result; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 保存变量 |
||||||
|
*//*
|
||||||
|
private void putRule(Map<String, String> map) throws Exception { |
||||||
|
for (Map.Entry<String, String> entry : map.entrySet()) { |
||||||
|
if (book != null) { |
||||||
|
book.putVariable(entry.getKey(), getString(entry.getValue())); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 分离并执行put规则 |
||||||
|
*//*
|
||||||
|
private String splitPutRule(String ruleStr) throws Exception { |
||||||
|
Matcher putMatcher = putPattern.matcher(ruleStr); |
||||||
|
while (putMatcher.find()) { |
||||||
|
ruleStr = ruleStr.replace(putMatcher.group(), ""); |
||||||
|
Map<String, String> map = new Gson().fromJson(putMatcher.group(1), MAP_STRING); |
||||||
|
putRule(map); |
||||||
|
} |
||||||
|
return ruleStr; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 替换@get |
||||||
|
*//*
|
||||||
|
public String replaceGet(String ruleStr) { |
||||||
|
Matcher getMatcher = getPattern.matcher(ruleStr); |
||||||
|
while (getMatcher.find()) { |
||||||
|
String value = ""; |
||||||
|
if (book != null && book.getVariableMap() != null) { |
||||||
|
value = book.getVariableMap().get(getMatcher.group(1)); |
||||||
|
if (value == null) value = ""; |
||||||
|
} |
||||||
|
ruleStr = ruleStr.replace(getMatcher.group(), value); |
||||||
|
} |
||||||
|
return ruleStr; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 正则替换 |
||||||
|
*//*
|
||||||
|
private String replaceRegex(String result, SourceRule rule) { |
||||||
|
if (!isEmpty(rule.replaceRegex)) { |
||||||
|
if (rule.replaceFirst) { |
||||||
|
Pattern pattern = Pattern.compile(rule.replaceRegex); |
||||||
|
Matcher matcher = pattern.matcher(String.valueOf(result)); |
||||||
|
if (matcher.find()) { |
||||||
|
result = matcher.group(0).replaceFirst(rule.replaceRegex, rule.replacement); |
||||||
|
} else { |
||||||
|
result = ""; |
||||||
|
} |
||||||
|
} else { |
||||||
|
result = String.valueOf(result).replaceAll(rule.replaceRegex, rule.replacement); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 替换JS |
||||||
|
*//*
|
||||||
|
@SuppressLint("DefaultLocale") |
||||||
|
private String replaceJs(String ruleStr) throws Exception { |
||||||
|
if (ruleStr.contains("{{") && ruleStr.contains("}}")) { |
||||||
|
Object jsEval; |
||||||
|
StringBuffer sb = new StringBuffer(ruleStr.length()); |
||||||
|
Matcher expMatcher = EXP_PATTERN.matcher(ruleStr); |
||||||
|
while (expMatcher.find()) { |
||||||
|
jsEval = evalJS(expMatcher.group(1), object); |
||||||
|
if (jsEval instanceof String) { |
||||||
|
expMatcher.appendReplacement(sb, (String) jsEval); |
||||||
|
} else if (jsEval instanceof Double && ((Double) jsEval) % 1.0 == 0) { |
||||||
|
expMatcher.appendReplacement(sb, String.format("%.0f", (Double) jsEval)); |
||||||
|
} else { |
||||||
|
expMatcher.appendReplacement(sb, String.valueOf(jsEval)); |
||||||
|
} |
||||||
|
} |
||||||
|
expMatcher.appendTail(sb); |
||||||
|
ruleStr = sb.toString(); |
||||||
|
} |
||||||
|
return ruleStr; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 分解规则生成规则列表 |
||||||
|
*//*
|
||||||
|
public List<SourceRule> splitSourceRule(String ruleStr) throws Exception { |
||||||
|
List<SourceRule> ruleList = new ArrayList<>(); |
||||||
|
if (isEmpty(ruleStr)) return ruleList; |
||||||
|
//检测Mode
|
||||||
|
Mode mode; |
||||||
|
if (StringUtils.startWithIgnoreCase(ruleStr, "@XPath:")) { |
||||||
|
mode = Mode.XPath; |
||||||
|
ruleStr = ruleStr.substring(7); |
||||||
|
} else if (StringUtils.startWithIgnoreCase(ruleStr, "@JSon:")) { |
||||||
|
mode = Mode.JSon; |
||||||
|
ruleStr = ruleStr.substring(6); |
||||||
|
} else { |
||||||
|
if (isJSON) { |
||||||
|
mode = Mode.JSon; |
||||||
|
} else { |
||||||
|
mode = Mode.Default; |
||||||
|
} |
||||||
|
} |
||||||
|
//分离put规则
|
||||||
|
ruleStr = splitPutRule(ruleStr); |
||||||
|
//替换get值
|
||||||
|
ruleStr = replaceGet(ruleStr); |
||||||
|
//替换js
|
||||||
|
ruleStr = replaceJs(ruleStr); |
||||||
|
//拆分为列表
|
||||||
|
int start = 0; |
||||||
|
String tmp; |
||||||
|
Matcher jsMatcher = JS_PATTERN.matcher(ruleStr); |
||||||
|
while (jsMatcher.find()) { |
||||||
|
if (jsMatcher.start() > start) { |
||||||
|
tmp = ruleStr.substring(start, jsMatcher.start()).replaceAll("\n", "").trim(); |
||||||
|
if (!isEmpty(tmp)) { |
||||||
|
ruleList.add(new SourceRule(tmp, mode)); |
||||||
|
} |
||||||
|
} |
||||||
|
ruleList.add(new SourceRule(jsMatcher.group(), Mode.Js)); |
||||||
|
start = jsMatcher.end(); |
||||||
|
} |
||||||
|
if (ruleStr.length() > start) { |
||||||
|
tmp = ruleStr.substring(start).replaceAll("\n", "").trim(); |
||||||
|
if (!isEmpty(tmp)) { |
||||||
|
ruleList.add(new SourceRule(tmp, mode)); |
||||||
|
} |
||||||
|
} |
||||||
|
return ruleList; |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 规则类 |
||||||
|
*//*
|
||||||
|
public static class SourceRule { |
||||||
|
Mode mode; |
||||||
|
String rule; |
||||||
|
String replaceRegex = ""; |
||||||
|
String replacement = ""; |
||||||
|
boolean replaceFirst = false; |
||||||
|
|
||||||
|
SourceRule(String ruleStr, Mode mainMode) { |
||||||
|
this.mode = mainMode; |
||||||
|
if (mode == Mode.Js) { |
||||||
|
if (ruleStr.startsWith("<js>")) { |
||||||
|
rule = ruleStr.substring(4, ruleStr.lastIndexOf("<")); |
||||||
|
} else { |
||||||
|
rule = ruleStr.substring(4); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (StringUtils.startWithIgnoreCase(ruleStr, "@XPath:")) { |
||||||
|
mode = Mode.XPath; |
||||||
|
rule = ruleStr.substring(7); |
||||||
|
} else if (StringUtils.startWithIgnoreCase(ruleStr, "//")) {//XPath特征很明显,无需配置单独的识别标头
|
||||||
|
mode = Mode.XPath; |
||||||
|
rule = ruleStr; |
||||||
|
} else if (StringUtils.startWithIgnoreCase(ruleStr, "@JSon:")) { |
||||||
|
mode = Mode.JSon; |
||||||
|
rule = ruleStr.substring(6); |
||||||
|
} else if (ruleStr.startsWith("$.")) { |
||||||
|
mode = Mode.JSon; |
||||||
|
rule = ruleStr; |
||||||
|
} else { |
||||||
|
rule = ruleStr; |
||||||
|
} |
||||||
|
//分离正则表达式
|
||||||
|
String[] ruleStrS = rule.trim().split("##"); |
||||||
|
rule = ruleStrS[0]; |
||||||
|
if (ruleStrS.length > 1) { |
||||||
|
replaceRegex = ruleStrS[1]; |
||||||
|
} |
||||||
|
if (ruleStrS.length > 2) { |
||||||
|
replacement = ruleStrS[2]; |
||||||
|
} |
||||||
|
if (ruleStrS.length > 3) { |
||||||
|
replaceFirst = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private enum Mode { |
||||||
|
XPath, JSon, Default, Js |
||||||
|
} |
||||||
|
|
||||||
|
public String put(String key, String value) { |
||||||
|
if (book != null) { |
||||||
|
book.putVariable(key, value); |
||||||
|
} |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public String get(String key) { |
||||||
|
if (book == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (book.getVariableMap() == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return book.getVariableMap().get(key); |
||||||
|
} |
||||||
|
|
||||||
|
*//**
|
||||||
|
* 执行JS |
||||||
|
*//*
|
||||||
|
private Object evalJS(String jsStr, Object result) throws Exception { |
||||||
|
SimpleBindings bindings = new SimpleBindings(); |
||||||
|
bindings.put("java", this); |
||||||
|
bindings.put("result", result); |
||||||
|
bindings.put("baseUrl", baseUrl); |
||||||
|
return SCRIPT_ENGINE.eval(jsStr, bindings); |
||||||
|
}*/ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,316 @@ |
|||||||
|
package xyz.fycz.myreader.model.analyzeRule; |
||||||
|
|
||||||
|
import android.annotation.SuppressLint; |
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import androidx.annotation.Keep; |
||||||
|
|
||||||
|
import com.google.gson.Gson; |
||||||
|
|
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import javax.script.SimpleBindings; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.util.StringHelper; |
||||||
|
import xyz.fycz.myreader.util.utils.JsExtensions; |
||||||
|
import xyz.fycz.myreader.util.utils.NetworkUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.StringUtils; |
||||||
|
import xyz.fycz.myreader.util.utils.UrlEncoderUtils; |
||||||
|
|
||||||
|
import static xyz.fycz.myreader.common.APPCONST.EXP_PATTERN; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.JS_PATTERN; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.MAP_STRING; |
||||||
|
import static xyz.fycz.myreader.common.APPCONST.SCRIPT_ENGINE; |
||||||
|
import static xyz.fycz.myreader.util.utils.NetworkUtils.headerPattern; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Created by GKF on 2018/1/24. |
||||||
|
* 搜索URL规则解析 |
||||||
|
*/ |
||||||
|
@Keep |
||||||
|
public class AnalyzeUrl implements JsExtensions { |
||||||
|
private static final Pattern pagePattern = Pattern.compile("\\{(.*?)\\}"); |
||||||
|
private String baseUrl; |
||||||
|
private String url; |
||||||
|
private String host; |
||||||
|
private String urlPath; |
||||||
|
private String queryStr; |
||||||
|
private Map<String, String> queryMap = new LinkedHashMap<>(); |
||||||
|
private Map<String, String> headerMap = new HashMap<>(); |
||||||
|
private String charCode = null; |
||||||
|
private UrlMode urlMode = UrlMode.DEFAULT; |
||||||
|
|
||||||
|
public AnalyzeUrl(String urlRule) throws Exception { |
||||||
|
this(urlRule, null, null, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
public AnalyzeUrl(String urlRule, Map<String, String> headerMapF, String baseUrl) throws Exception { |
||||||
|
this(urlRule, null, null, headerMapF, baseUrl); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale") |
||||||
|
public AnalyzeUrl(String ruleUrl, final String key, final Integer page, Map<String, String> headerMapF, String baseUrl) throws Exception { |
||||||
|
if (!TextUtils.isEmpty(baseUrl)) { |
||||||
|
this.baseUrl = headerPattern.matcher(baseUrl).replaceAll(""); |
||||||
|
} |
||||||
|
//替换关键字
|
||||||
|
if (!StringHelper.isEmpty(key)) { |
||||||
|
// 处理searchKey=searchKey的情况
|
||||||
|
if (ruleUrl.matches("=[\\s{(]*searchKey")) |
||||||
|
ruleUrl = ruleUrl.replaceFirst("=[\\s{(]*searchKey", "=" + key); |
||||||
|
else |
||||||
|
ruleUrl = ruleUrl.replace("searchKey", key); |
||||||
|
} |
||||||
|
//判断是否有下一页
|
||||||
|
if (page != null && page > 1 && !ruleUrl.contains("searchPage")) |
||||||
|
throw new Exception("没有下一页"); |
||||||
|
//替换js
|
||||||
|
ruleUrl = replaceJs(ruleUrl, baseUrl, page, key); |
||||||
|
//解析Header
|
||||||
|
ruleUrl = analyzeHeader(ruleUrl, headerMapF); |
||||||
|
//分离编码规则
|
||||||
|
ruleUrl = splitCharCode(ruleUrl); |
||||||
|
//设置页数
|
||||||
|
ruleUrl = analyzePage(ruleUrl, page); |
||||||
|
//执行规则列表
|
||||||
|
List<String> ruleList = splitRule(ruleUrl); |
||||||
|
for (String rule : ruleList) { |
||||||
|
if (rule.startsWith("<js>")) { |
||||||
|
rule = rule.substring(4, rule.lastIndexOf("<")); |
||||||
|
ruleUrl = (String) evalJS(rule, ruleUrl); |
||||||
|
} else if (rule.startsWith("@js:")) { |
||||||
|
rule = rule.substring(4); |
||||||
|
ruleUrl = (String) evalJS(rule, ruleUrl); |
||||||
|
} else { |
||||||
|
ruleUrl = rule.replace("@result", ruleUrl); |
||||||
|
} |
||||||
|
} |
||||||
|
//分离post参数
|
||||||
|
String[] ruleUrlS = ruleUrl.split("@"); |
||||||
|
if (ruleUrlS.length > 1) { |
||||||
|
urlMode = UrlMode.POST; |
||||||
|
} else { |
||||||
|
//分离get参数
|
||||||
|
ruleUrlS = ruleUrlS[0].split("\\?"); |
||||||
|
if (ruleUrlS.length > 1) { |
||||||
|
urlMode = UrlMode.GET; |
||||||
|
} |
||||||
|
} |
||||||
|
generateUrlPath(ruleUrlS[0]); |
||||||
|
if (urlMode != UrlMode.DEFAULT) { |
||||||
|
analyzeQuery(ruleUrlS[1]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解析Header |
||||||
|
*/ |
||||||
|
private String analyzeHeader(String ruleUrl, Map<String, String> headerMapF) { |
||||||
|
if (headerMapF != null) { |
||||||
|
headerMap.putAll(headerMapF); |
||||||
|
} |
||||||
|
Matcher matcher = headerPattern.matcher(ruleUrl); |
||||||
|
if (matcher.find()) { |
||||||
|
String find = matcher.group(0); |
||||||
|
ruleUrl = ruleUrl.replace(find, ""); |
||||||
|
find = find.substring(8); |
||||||
|
try { |
||||||
|
Map<String, String> map = new Gson().fromJson(find, MAP_STRING); |
||||||
|
headerMap.putAll(map); |
||||||
|
} catch (Exception ignored) { |
||||||
|
} |
||||||
|
} |
||||||
|
return ruleUrl; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 分离编码规则 |
||||||
|
*/ |
||||||
|
private String splitCharCode(String rule) { |
||||||
|
String[] ruleUrlS = rule.split("\\|"); |
||||||
|
if (ruleUrlS.length > 1) { |
||||||
|
if (!TextUtils.isEmpty(ruleUrlS[1])) { |
||||||
|
String[] qtS = ruleUrlS[1].split("&"); |
||||||
|
for (String qt : qtS) { |
||||||
|
String[] gz = qt.split("="); |
||||||
|
if (gz[0].equals("char")) { |
||||||
|
charCode = gz[1]; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return ruleUrlS[0]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解析页数 |
||||||
|
*/ |
||||||
|
private String analyzePage(String ruleUrl, final Integer searchPage) { |
||||||
|
if (searchPage == null) return ruleUrl; |
||||||
|
Matcher matcher = pagePattern.matcher(ruleUrl); |
||||||
|
while (matcher.find()) { |
||||||
|
String[] pages = matcher.group(1).split(","); |
||||||
|
if (searchPage <= pages.length) { |
||||||
|
ruleUrl = ruleUrl.replace(matcher.group(), pages[searchPage - 1].trim()); |
||||||
|
} else { |
||||||
|
ruleUrl = ruleUrl.replace(matcher.group(), pages[pages.length - 1].trim()); |
||||||
|
} |
||||||
|
} |
||||||
|
return ruleUrl.replace("searchPage-1", String.valueOf(searchPage - 1)) |
||||||
|
.replace("searchPage+1", String.valueOf(searchPage + 1)) |
||||||
|
.replace("searchPage", String.valueOf(searchPage)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 替换js |
||||||
|
*/ |
||||||
|
@SuppressLint("DefaultLocale") |
||||||
|
private String replaceJs(String ruleUrl, String baseUrl, Integer searchPage, String searchKey) throws Exception { |
||||||
|
if (ruleUrl.contains("{{") && ruleUrl.contains("}}")) { |
||||||
|
Object jsEval; |
||||||
|
StringBuffer sb = new StringBuffer(ruleUrl.length()); |
||||||
|
SimpleBindings simpleBindings = new SimpleBindings() {{ |
||||||
|
this.put("baseUrl", baseUrl); |
||||||
|
this.put("searchPage", searchPage); |
||||||
|
this.put("searchKey", searchKey); |
||||||
|
}}; |
||||||
|
Matcher expMatcher = EXP_PATTERN.matcher(ruleUrl); |
||||||
|
while (expMatcher.find()) { |
||||||
|
jsEval = SCRIPT_ENGINE.eval(expMatcher.group(1), simpleBindings); |
||||||
|
if (jsEval instanceof String) { |
||||||
|
expMatcher.appendReplacement(sb, (String) jsEval); |
||||||
|
} else if (jsEval instanceof Double && ((Double) jsEval) % 1.0 == 0) { |
||||||
|
expMatcher.appendReplacement(sb, String.format("%.0f", (Double) jsEval)); |
||||||
|
} else { |
||||||
|
expMatcher.appendReplacement(sb, String.valueOf(jsEval)); |
||||||
|
} |
||||||
|
} |
||||||
|
expMatcher.appendTail(sb); |
||||||
|
ruleUrl = sb.toString(); |
||||||
|
} |
||||||
|
return ruleUrl; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解析QueryMap |
||||||
|
*/ |
||||||
|
private void analyzeQuery(String allQuery) throws Exception { |
||||||
|
queryStr = allQuery; |
||||||
|
String[] queryS = allQuery.split("&"); |
||||||
|
for (String query : queryS) { |
||||||
|
String[] queryM = query.split("="); |
||||||
|
String value = queryM.length > 1 ? queryM[1] : ""; |
||||||
|
if (TextUtils.isEmpty(charCode)) { |
||||||
|
if (UrlEncoderUtils.hasUrlEncoded(value)) { |
||||||
|
queryMap.put(queryM[0], value); |
||||||
|
} else { |
||||||
|
queryMap.put(queryM[0], URLEncoder.encode(value, "UTF-8")); |
||||||
|
} |
||||||
|
} else if (charCode.equals("escape")) { |
||||||
|
queryMap.put(queryM[0], StringUtils.escape(value)); |
||||||
|
} else { |
||||||
|
queryMap.put(queryM[0], URLEncoder.encode(value, charCode)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 拆分规则 |
||||||
|
*/ |
||||||
|
private List<String> splitRule(String ruleStr) { |
||||||
|
List<String> ruleList = new ArrayList<>(); |
||||||
|
Matcher jsMatcher = JS_PATTERN.matcher(ruleStr); |
||||||
|
int start = 0; |
||||||
|
String tmp; |
||||||
|
while (jsMatcher.find()) { |
||||||
|
if (jsMatcher.start() > start) { |
||||||
|
tmp = ruleStr.substring(start, jsMatcher.start()).replaceAll("\n", "").trim(); |
||||||
|
if (!TextUtils.isEmpty(tmp)) { |
||||||
|
ruleList.add(tmp); |
||||||
|
} |
||||||
|
} |
||||||
|
ruleList.add(jsMatcher.group()); |
||||||
|
start = jsMatcher.end(); |
||||||
|
} |
||||||
|
if (ruleStr.length() > start) { |
||||||
|
tmp = ruleStr.substring(start).replaceAll("\n", "").trim(); |
||||||
|
if (!TextUtils.isEmpty(tmp)) { |
||||||
|
ruleList.add(tmp); |
||||||
|
} |
||||||
|
} |
||||||
|
return ruleList; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 分解URL |
||||||
|
*/ |
||||||
|
private void generateUrlPath(String ruleUrl) { |
||||||
|
url = NetworkUtils.getAbsoluteURL(baseUrl, ruleUrl); |
||||||
|
host = StringUtils.getBaseUrl(url); |
||||||
|
urlPath = url.substring(host.length()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 执行JS |
||||||
|
*/ |
||||||
|
private Object evalJS(String jsStr, Object result) throws Exception { |
||||||
|
SimpleBindings bindings = new SimpleBindings(); |
||||||
|
bindings.put("result", result); |
||||||
|
return SCRIPT_ENGINE.eval(jsStr, bindings); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCharCode() { |
||||||
|
return charCode; |
||||||
|
} |
||||||
|
|
||||||
|
public String getHost() { |
||||||
|
return host; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPath() { |
||||||
|
return urlPath; |
||||||
|
} |
||||||
|
|
||||||
|
public String getUrl() { |
||||||
|
return url; |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, String> getQueryMap() { |
||||||
|
return queryMap; |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, String> getHeaderMap() { |
||||||
|
return headerMap; |
||||||
|
} |
||||||
|
|
||||||
|
public String getQueryStr() { |
||||||
|
return queryStr; |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] getPostData() { |
||||||
|
StringBuilder builder = new StringBuilder(); |
||||||
|
Set<String> keys = queryMap.keySet(); |
||||||
|
for (String key : keys) { |
||||||
|
builder.append(String.format("%s=%s&", key, queryMap.get(key))); |
||||||
|
} |
||||||
|
builder.deleteCharAt(builder.lastIndexOf("&")); |
||||||
|
return builder.toString().getBytes(); |
||||||
|
} |
||||||
|
|
||||||
|
public UrlMode getUrlMode() { |
||||||
|
return urlMode; |
||||||
|
} |
||||||
|
|
||||||
|
public enum UrlMode { |
||||||
|
GET, POST, DEFAULT |
||||||
|
} |
||||||
|
} |
@ -1,186 +0,0 @@ |
|||||||
package xyz.fycz.myreader.ui.dialog; |
|
||||||
|
|
||||||
import android.annotation.SuppressLint; |
|
||||||
import android.content.Context; |
|
||||||
import android.os.Handler; |
|
||||||
import android.os.Message; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.application.App; |
|
||||||
import xyz.fycz.myreader.webapi.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
import xyz.fycz.myreader.webapi.crawler.*; |
|
||||||
import xyz.fycz.myreader.entity.SearchBookBean; |
|
||||||
import xyz.fycz.myreader.greendao.entity.Book; |
|
||||||
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; |
|
||||||
import xyz.fycz.myreader.webapi.CommonApi; |
|
||||||
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; |
|
||||||
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; |
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.net.URLEncoder; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* @author fengyue |
|
||||||
* @date 2020/5/19 17:35 |
|
||||||
*/ |
|
||||||
public class ChangeSourceDialog { |
|
||||||
private Context context; |
|
||||||
private Book mBook; |
|
||||||
private ConcurrentMultiValueMap<SearchBookBean, Book> mBooks = new ConcurrentMultiValueMap<>(); |
|
||||||
private ArrayList<Book> aBooks; |
|
||||||
private SearchBookBean sbb; |
|
||||||
private boolean isSearchSuccess; |
|
||||||
private int threadCount; |
|
||||||
private ResultCallback rc; |
|
||||||
private boolean isGetOneBook = false; |
|
||||||
private Book oneBook; |
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private Handler mHandler = new Handler() { |
|
||||||
@Override |
|
||||||
public void handleMessage(Message msg) { |
|
||||||
switch (msg.what) { |
|
||||||
case 1: |
|
||||||
if (isGetOneBook){ |
|
||||||
rc.onFinish(oneBook, 0); |
|
||||||
}else { |
|
||||||
if (threadCount == 0) { |
|
||||||
createaBooks(); |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
case 2: |
|
||||||
if (!isSearchSuccess && threadCount == 0) { |
|
||||||
if (!isGetOneBook|| oneBook == null) { |
|
||||||
rc.onError(new Exception()); |
|
||||||
} |
|
||||||
}else if (threadCount == 0){ |
|
||||||
if (isGetOneBook){ |
|
||||||
rc.onFinish(oneBook, 0); |
|
||||||
}else { |
|
||||||
createaBooks(); |
|
||||||
} |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
public ChangeSourceDialog(Context context, Book mBook) { |
|
||||||
this.context = context; |
|
||||||
this.mBook = mBook; |
|
||||||
sbb = new SearchBookBean(mBook.getName(), mBook.getAuthor()); |
|
||||||
} |
|
||||||
|
|
||||||
public void init(ResultCallback rc) { |
|
||||||
this.rc = rc; |
|
||||||
getData(); |
|
||||||
} |
|
||||||
|
|
||||||
public void initOneBook(ResultCallback rc){ |
|
||||||
this.rc = rc; |
|
||||||
getData(); |
|
||||||
isGetOneBook = true; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取搜索数据 |
|
||||||
*/ |
|
||||||
private void getData() { |
|
||||||
mBooks.clear(); |
|
||||||
ArrayList<ReadCrawler> readCrawlers = ReadCrawlerUtil.getReadCrawlers(); |
|
||||||
threadCount = readCrawlers.size(); |
|
||||||
if (threadCount == 0){ |
|
||||||
if (isGetOneBook){ |
|
||||||
ToastUtils.showWarring("当前书源已全部禁用,无法搜索!"); |
|
||||||
}else { |
|
||||||
ToastUtils.showWarring("当前书源已全部禁用,无法换源!"); |
|
||||||
} |
|
||||||
rc.onError(new Exception()); |
|
||||||
return; |
|
||||||
} |
|
||||||
isSearchSuccess = false; |
|
||||||
for (ReadCrawler readCrawler : readCrawlers){ |
|
||||||
searchBookByCrawler(readCrawler, readCrawler.getSearchCharset()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void searchBookByCrawler(final ReadCrawler rc, String charset) { |
|
||||||
String searchKey = mBook.getName(); |
|
||||||
if (charset.toLowerCase().equals("gbk")) { |
|
||||||
try { |
|
||||||
searchKey = URLEncoder.encode(mBook.getName(), charset); |
|
||||||
} catch (UnsupportedEncodingException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
CommonApi.search(searchKey, rc, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
final ConcurrentMultiValueMap<SearchBookBean, Book> cmvm = |
|
||||||
(ConcurrentMultiValueMap<SearchBookBean, Book>) o; |
|
||||||
if (isGetOneBook){ |
|
||||||
if (oneBook != null){ |
|
||||||
return; |
|
||||||
} |
|
||||||
oneBook = cmvm.getValue(sbb, 0); |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
App.getApplication().shutdownThreadPool(); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (rc instanceof BookInfoCrawler) { |
|
||||||
BookInfoCrawler bic = (BookInfoCrawler) rc; |
|
||||||
final List<Book> aBooks = cmvm.getValues(sbb); |
|
||||||
if (aBooks != null) { |
|
||||||
for (int i = 0; i < aBooks.size(); i++) { |
|
||||||
Book book = aBooks.get(i); |
|
||||||
final int finalI = i; |
|
||||||
CommonApi.getBookInfo(book, bic, new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
if (finalI == aBooks.size() - 1) { |
|
||||||
mBooks.addAll(cmvm); |
|
||||||
isSearchSuccess = true; |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
} |
|
||||||
} else { |
|
||||||
isSearchSuccess = true; |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
} else { |
|
||||||
mBooks.addAll(cmvm); |
|
||||||
isSearchSuccess = true; |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(1)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
threadCount--; |
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(2)); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
private void createaBooks() { |
|
||||||
aBooks = (ArrayList<Book>) mBooks.getValues(sbb); |
|
||||||
rc.onFinish(aBooks, 1); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,82 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
|
||||||
|
import org.jsoup.Connection; |
||||||
|
import org.jsoup.Jsoup; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import xyz.fycz.myreader.model.analyzeRule.AnalyzeUrl; |
||||||
|
import xyz.fycz.myreader.util.HttpUtil; |
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"}) |
||||||
|
public interface JsExtensions { |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现跨域访问,不能删 |
||||||
|
*/ |
||||||
|
/*default String ajax(String urlStr) { |
||||||
|
try { |
||||||
|
AnalyzeUrl analyzeUrl = new AnalyzeUrl(urlStr); |
||||||
|
Response<String> response = BaseModelImpl.getInstance().getResponseO(analyzeUrl) |
||||||
|
.blockingFirst(); |
||||||
|
return response.body(); |
||||||
|
} catch (Exception e) { |
||||||
|
return e.getLocalizedMessage(); |
||||||
|
} |
||||||
|
}*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现解码,不能删 |
||||||
|
*/ |
||||||
|
default String base64Decoder(String base64) { |
||||||
|
return StringUtils.base64Decode(base64); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 章节数转数字 |
||||||
|
*/ |
||||||
|
default String toNumChapter(String s) { |
||||||
|
if (s == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Pattern pattern = Pattern.compile("(第)(.+?)(章)"); |
||||||
|
Matcher matcher = pattern.matcher(s); |
||||||
|
if (matcher.find()) { |
||||||
|
return matcher.group(1) + StringUtils.stringToInt(matcher.group(2)) + matcher.group(3); |
||||||
|
} |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现重定向拦截,不能删 |
||||||
|
*/ |
||||||
|
default Connection.Response get(String urlStr, Map<String, String> headers) throws IOException { |
||||||
|
return Jsoup.connect(urlStr) |
||||||
|
.sslSocketFactory(HttpUtil.createSSLSocketFactory()) |
||||||
|
.ignoreContentType(true) |
||||||
|
.followRedirects(false) |
||||||
|
.headers(headers) |
||||||
|
.method(Connection.Method.GET) |
||||||
|
.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* js实现重定向拦截,不能删 |
||||||
|
*/ |
||||||
|
default Connection.Response post(String urlStr, String body, Map<String, String> headers) throws IOException { |
||||||
|
return Jsoup.connect(urlStr) |
||||||
|
.sslSocketFactory(HttpUtil.createSSLSocketFactory()) |
||||||
|
.ignoreContentType(true) |
||||||
|
.followRedirects(false) |
||||||
|
.requestBody(body) |
||||||
|
.headers(headers) |
||||||
|
.method(Connection.Method.POST) |
||||||
|
.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
package xyz.fycz.myreader.util.utils; |
||||||
|
|
||||||
|
import java.util.BitSet; |
||||||
|
|
||||||
|
/** |
||||||
|
* 这里会有误差,比如输入一个字符串 123+456,它到底是原文就是123+456还是123 456做了urlEncode后的内容呢?<br> |
||||||
|
* 其实问题是一样的,比如遇到123%2B456,它到底是原文即使如此,还是123+456 urlEncode后的呢? <br> |
||||||
|
* 在这里,我认为只要符合urlEncode规范的,就当作已经urlEncode过了<br> |
||||||
|
* 毕竟这个方法的初衷就是判断string是否urlEncode过<br> |
||||||
|
*/ |
||||||
|
public class UrlEncoderUtils { |
||||||
|
private static BitSet dontNeedEncoding; |
||||||
|
|
||||||
|
static { |
||||||
|
dontNeedEncoding = new BitSet(256); |
||||||
|
int i; |
||||||
|
for (i = 'a'; i <= 'z'; i++) { |
||||||
|
dontNeedEncoding.set(i); |
||||||
|
} |
||||||
|
for (i = 'A'; i <= 'Z'; i++) { |
||||||
|
dontNeedEncoding.set(i); |
||||||
|
} |
||||||
|
for (i = '0'; i <= '9'; i++) { |
||||||
|
dontNeedEncoding.set(i); |
||||||
|
} |
||||||
|
dontNeedEncoding.set('+'); |
||||||
|
dontNeedEncoding.set('-'); |
||||||
|
dontNeedEncoding.set('_'); |
||||||
|
dontNeedEncoding.set('.'); |
||||||
|
dontNeedEncoding.set('$'); |
||||||
|
dontNeedEncoding.set(':'); |
||||||
|
dontNeedEncoding.set('('); |
||||||
|
dontNeedEncoding.set(')'); |
||||||
|
dontNeedEncoding.set('!'); |
||||||
|
dontNeedEncoding.set('*'); |
||||||
|
dontNeedEncoding.set('@'); |
||||||
|
dontNeedEncoding.set('&'); |
||||||
|
dontNeedEncoding.set('#'); |
||||||
|
dontNeedEncoding.set(','); |
||||||
|
dontNeedEncoding.set('['); |
||||||
|
dontNeedEncoding.set(']'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 支持JAVA的URLEncoder.encode出来的string做判断。 即: 将' '转成'+' |
||||||
|
* 0-9a-zA-Z保留 <br> |
||||||
|
* ! * ' ( ) ; : @ & = + $ , / ? # [ ] 保留 |
||||||
|
* 其他字符转成%XX的格式,X是16进制的大写字符,范围是[0-9A-F] |
||||||
|
*/ |
||||||
|
public static boolean hasUrlEncoded(String str) { |
||||||
|
boolean needEncode = false; |
||||||
|
for (int i = 0; i < str.length(); i++) { |
||||||
|
char c = str.charAt(i); |
||||||
|
if (dontNeedEncoding.get((int) c)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (c == '%' && (i + 2) < str.length()) { |
||||||
|
// 判断是否符合urlEncode规范
|
||||||
|
char c1 = str.charAt(++i); |
||||||
|
char c2 = str.charAt(++i); |
||||||
|
if (isDigit16Char(c1) && isDigit16Char(c2)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
// 其他字符,肯定需要urlEncode
|
||||||
|
needEncode = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return !needEncode; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 判断c是否是16进制的字符 |
||||||
|
*/ |
||||||
|
private static boolean isDigit16Char(char c) { |
||||||
|
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,231 +0,0 @@ |
|||||||
package xyz.fycz.myreader.webapi; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.common.ErrorCode; |
|
||||||
import xyz.fycz.myreader.entity.JsonModel; |
|
||||||
import xyz.fycz.myreader.util.HttpUtil; |
|
||||||
import com.google.gson.Gson; |
|
||||||
|
|
||||||
import xyz.fycz.myreader.util.utils.GsonExtensionsKt; |
|
||||||
import xyz.fycz.myreader.webapi.callback.JsonCallback; |
|
||||||
import xyz.fycz.myreader.webapi.callback.ResultCallback; |
|
||||||
import xyz.fycz.myreader.util.ToastUtils; |
|
||||||
|
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
public class BaseApi { |
|
||||||
|
|
||||||
/** |
|
||||||
* post通用返回实体api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param c 返回的实体类型 |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void postCommonApi(String url, Map<String, Object> params, final Class c, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpPost(url, HttpUtil.makePostOutput(params), new JsonCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(JsonModel jsonModel) { |
|
||||||
if (jsonModel.isSuccess()) { |
|
||||||
callback.onFinish(new Gson().fromJson(jsonModel.getResult(),c), jsonModel.getError()); |
|
||||||
} else { |
|
||||||
noSuccess(jsonModel,callback); |
|
||||||
} |
|
||||||
} |
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
error(e,callback); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* post通用返回字符串api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void postCommonReturnStringApi(String url, Map<String, Object> params, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpPost(url, HttpUtil.makePostOutput(params), new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
callback.onFinish(o, code); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
callback.onError(e); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* get通用返回字符串api |
|
||||||
* 通过api获取蓝奏云直链 |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void postLanzousApi(String url, Map<String, Object> params, final ResultCallback callback, final String referer) { |
|
||||||
HttpDataSource.httpPost(url, HttpUtil.makePostOutput(params), new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
callback.onFinish(o, code); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
callback.onError(e); |
|
||||||
} |
|
||||||
}, referer); |
|
||||||
} |
|
||||||
/** |
|
||||||
* get通用返回实体api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param c 返回的实体类型 |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void getCommonApi(String url, Map<String, Object> params, final Class c, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpGet(HttpUtil.makeURL(url,params), new JsonCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(JsonModel jsonModel) { |
|
||||||
if (jsonModel.isSuccess()) { |
|
||||||
callback.onFinish(new Gson().fromJson(jsonModel.getResult(),c), jsonModel.getError()); |
|
||||||
} else { |
|
||||||
noSuccess(jsonModel,callback); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
error(e,callback); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* get通用返回字符串api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void getCommonReturnStringApi(String url, Map<String, Object> params, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpGet(HttpUtil.makeURL(url,params), new JsonCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(JsonModel jsonModel) { |
|
||||||
if (jsonModel.isSuccess()) { |
|
||||||
callback.onFinish(jsonModel.getResult(), jsonModel.getError()); |
|
||||||
} else { |
|
||||||
noSuccess(jsonModel, callback); |
|
||||||
} |
|
||||||
} |
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
error(e,callback); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
/** |
|
||||||
* get通用返回字符串api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void getCommonReturnStringApi2(String url, Map<String, Object> params, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpGet(HttpUtil.makeURL(url, params), new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
callback.onFinish(o,code); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
callback.onError(e); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* get通用返回Html字符串api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
public static void getCommonReturnHtmlStringApi(String url, Map<String, Object> params, String charsetName, boolean isRefresh, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpGet_html(HttpUtil.makeURL(url, params), charsetName, isRefresh ,new ResultCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(Object o, int code) { |
|
||||||
callback.onFinish(o,code); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
callback.onError(e); |
|
||||||
// error(e,callback);
|
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* get通用获取实体列表api |
|
||||||
* @param url |
|
||||||
* @param params |
|
||||||
* @param c 返回是列表实体类型 |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
protected static void getCommonListApi(String url, Map<String, Object> params, final Class c, final ResultCallback callback) { |
|
||||||
HttpDataSource.httpGet(HttpUtil.makeURL(url,params), new JsonCallback() { |
|
||||||
@Override |
|
||||||
public void onFinish(JsonModel jsonModel) { |
|
||||||
if (jsonModel.isSuccess()) { |
|
||||||
try { |
|
||||||
callback.onFinish(GsonExtensionsKt.getGSON().fromJson(jsonModel.getResult(), c), jsonModel.getError()); |
|
||||||
}catch (Exception e){ |
|
||||||
callback.onError(e); |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
noSuccess(jsonModel,callback); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onError(Exception e) { |
|
||||||
error(e,callback); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* api异常处理 |
|
||||||
* @param e |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
private static void error(Exception e, final ResultCallback callback){ |
|
||||||
/* if (e.toString().contains("SocketTimeoutException") || e.toString().contains("UnknownHostException")) { |
|
||||||
TextHelper.showText("网络连接超时,请检查网络"); |
|
||||||
}*/ |
|
||||||
e.printStackTrace(); |
|
||||||
callback.onError(e); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* api请求失败处理 |
|
||||||
* @param jsonModel |
|
||||||
* @param callback |
|
||||||
*/ |
|
||||||
private static void noSuccess(JsonModel jsonModel, ResultCallback callback){ |
|
||||||
if (!jsonModel.isSuccess()) { |
|
||||||
if (jsonModel.getError() == ErrorCode.no_security) { |
|
||||||
ToastUtils.showWarring("登录过期,请重新登录"); |
|
||||||
} else { |
|
||||||
if (jsonModel.getError() == 0) { |
|
||||||
callback.onFinish(jsonModel.getResult(), -1); |
|
||||||
} else { |
|
||||||
callback.onFinish(jsonModel.getResult(), jsonModel.getError()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue