pull/21/head
fengyuecanzhu 3 years ago
parent d4190694a9
commit eb7b98b429
  1. 2
      app/build.gradle
  2. 14
      app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
  3. 31
      app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/BookSource.java
  4. 24
      app/src/main/java/xyz/fycz/myreader/greendao/entity/rule/ContentRule.java
  5. 32
      app/src/main/java/xyz/fycz/myreader/model/third2/analyzeRule/JsExtensions.java
  6. 166
      app/src/main/java/xyz/fycz/myreader/model/third3/BaseSource.kt
  7. 5
      app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeRule.kt
  8. 19
      app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/AnalyzeUrl.kt
  9. 5
      app/src/main/java/xyz/fycz/myreader/model/third3/analyzeRule/JsExtensions.kt
  10. 4
      app/src/main/java/xyz/fycz/myreader/model/third3/webBook/BookChapterList.kt
  11. 4
      app/src/main/java/xyz/fycz/myreader/model/third3/webBook/BookContent.kt
  12. 2
      app/src/main/java/xyz/fycz/myreader/model/third3/webBook/BookList.kt
  13. 13
      app/src/main/java/xyz/fycz/myreader/model/third3/webBook/WebBook.kt
  14. 2
      app/src/main/java/xyz/fycz/myreader/ui/adapter/SearchAdapter.kt
  15. 58
      app/src/main/java/xyz/fycz/myreader/util/utils/EncoderUtils.kt
  16. 8
      app/src/main/java/xyz/fycz/myreader/util/utils/HtmlFormatter.kt
  17. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiJianReadCrawler.java
  18. 6
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGe44ReadCrawler.java
  19. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/EWenXueReadCrawler.java
  20. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/FYReadCrawler.java
  21. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/HongChenReadCrawler.java
  22. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PiaoTianReadCrawler.java
  23. 1
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/PinShuReadCrawler2.java
  24. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ShiGuangReadCrawler.java
  25. 7
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ShuHaiGeReadCrawler.java
  26. 4
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/TianLaiReadCrawler.java
  27. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/XBiQuGeReadCrawler.java
  28. 4
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/XS7ReadCrawler2.java
  29. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/XiaGuReadCrawler.java
  30. 4
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZW37ReadCrawler.java
  31. 4
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZaiShuYuanReadCrawler.java
  32. 2
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ZuoPinReadCrawler.java

@ -224,7 +224,7 @@ dependencies {
//JS
//noinspection GradleDependency
implementation 'com.github.gedoor:rhino-android:1.3'
implementation 'com.github.gedoor:rhino-android:1.6'
//XXPermissions
implementation 'com.github.getActivity:XXPermissions:11.2'

@ -191,6 +191,18 @@ object EditEntityUtil {
"填写后正文时将会不断地从下一页获取内容,直至下一页URL为空时停止,注意:千万不要获取恒存在的URL,否则将出现死循环甚至崩溃"
)
)
add(
EditEntity(
"webJs", contentRule?.webJs, R.string.rule_web_js,
""
)
)
add(
EditEntity(
"sourceRegex", contentRule?.sourceRegex, R.string.rule_source_regex,
""
)
)
add(
EditEntity(
"replaceRegex", contentRule?.replaceRegex, R.string.rule_replace_regex,
@ -309,6 +321,8 @@ object EditEntityUtil {
"content" -> contentRule.content = it.value
"contentBaseUrl" -> contentRule.contentBaseUrl = it.value
"contentUrlNext" -> contentRule.contentUrlNext = it.value
"webJs" -> contentRule.webJs = it.value
"sourceRegex" -> contentRule.sourceRegex = it.value
"replaceRegex" -> contentRule.replaceRegex = it.value
}
}

@ -5,6 +5,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
@ -24,6 +25,7 @@ import xyz.fycz.myreader.greendao.convert.FindRuleConvert;
import xyz.fycz.myreader.greendao.convert.InfoRuleConvert;
import xyz.fycz.myreader.greendao.convert.SearchRuleConvert;
import xyz.fycz.myreader.greendao.convert.TocRuleConvert;
import xyz.fycz.myreader.model.third3.BaseSource;
import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
@ -32,7 +34,7 @@ import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals;
* @date 2021/2/8 17:37
*/
@Entity
public class BookSource implements Parcelable, Cloneable {
public class BookSource extends BaseSource implements Parcelable, Cloneable {
//基本信息
@Id
private String sourceUrl;
@ -422,4 +424,31 @@ public class BookSource implements Parcelable, Cloneable {
public void setConcurrentRate(String concurrentRate) {
this.concurrentRate = concurrentRate;
}
@Override
public String getHeader() {
return sourceHeaders;
}
@Override
public void setHeader(@Nullable String header) {
this.sourceHeaders = header;
}
@NonNull
@Override
public String getTag() {
return sourceName;
}
@NonNull
@Override
public String getKey() {
return sourceUrl;
}
@Override
public BookSource getSource() {
return this;
}
}

@ -19,12 +19,16 @@ public class ContentRule implements Parcelable {
private String content;
private String contentBaseUrl;
private String contentUrlNext;
private String webJs;
private String sourceRegex;
private String replaceRegex;
protected ContentRule(Parcel in) {
content = in.readString();
contentBaseUrl = in.readString();
contentUrlNext = in.readString();
webJs = in.readString();
sourceRegex = in.readString();
replaceRegex = in.readString();
}
@ -33,6 +37,8 @@ public class ContentRule implements Parcelable {
dest.writeString(content);
dest.writeString(contentBaseUrl);
dest.writeString(contentUrlNext);
dest.writeString(webJs);
dest.writeString(sourceRegex);
dest.writeString(replaceRegex);
}
@ -62,6 +68,8 @@ public class ContentRule implements Parcelable {
return stringEquals(content, that.content) &&
stringEquals(contentBaseUrl, that.contentBaseUrl) &&
stringEquals(contentUrlNext, that.contentUrlNext) &&
stringEquals(webJs, that.webJs) &&
stringEquals(sourceRegex, that.sourceRegex) &&
stringEquals(replaceRegex, that.replaceRegex);
}
@ -93,6 +101,22 @@ public class ContentRule implements Parcelable {
this.contentUrlNext = contentUrlNext;
}
public String getWebJs() {
return webJs;
}
public void setWebJs(String webJs) {
this.webJs = webJs;
}
public String getSourceRegex() {
return sourceRegex;
}
public void setSourceRegex(String sourceRegex) {
this.sourceRegex = sourceRegex;
}
public String getReplaceRegex() {
return replaceRegex;
}

@ -252,7 +252,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
default byte[] aesDecodeToByteArray(String str, String key, String transformation, String iv) {
default byte[] aesDecodeToByteArray(String str, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.decryptAES(
str.getBytes(StandardCharsets.UTF_8),
@ -262,7 +262,7 @@ public interface JsExtensions {
);
}
default byte[] aesDecodeToByteArray(String str, String key, String transformation) {
default byte[] aesDecodeToByteArray(String str, String key, String transformation) throws Exception {
return aesDecodeToByteArray(str, key, transformation, "");
}
@ -275,7 +275,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
default String aesDecodeToString(String str, String key, String transformation, String iv) {
default String aesDecodeToString(String str, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesDecodeToByteArray(str, key, transformation, iv);
if (bytes == null) {
return "";
@ -283,7 +283,7 @@ public interface JsExtensions {
return new String(bytes);
}
default String aesDecodeToString(String str, String key, String transformation) {
default String aesDecodeToString(String str, String key, String transformation) throws Exception {
return aesDecodeToString(str, key, transformation, "");
}
@ -296,7 +296,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation, String iv) {
default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.decryptBase64AES(
str.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@ -305,7 +305,7 @@ public interface JsExtensions {
);
}
default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation) {
default byte[] aesBase64DecodeToByteArray(String str, String key, String transformation) throws Exception {
return aesBase64DecodeToByteArray(str, key, transformation, "");
}
@ -319,7 +319,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量
*/
default String aesBase64DecodeToString(String str, String key, String transformation, String iv) {
default String aesBase64DecodeToString(String str, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesBase64DecodeToByteArray(str, key, transformation, iv);
if (bytes == null) {
return "";
@ -327,7 +327,7 @@ public interface JsExtensions {
return new String(bytes);
}
default String aesBase64DecodeToString(String str, String key, String transformation) {
default String aesBase64DecodeToString(String str, String key, String transformation) throws Exception {
return aesBase64DecodeToString(str, key, transformation, "");
}
@ -339,7 +339,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
default byte[] aesEncodeToByteArray(String data, String key, String transformation, String iv) {
default byte[] aesEncodeToByteArray(String data, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.encryptAES(
data.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@ -348,7 +348,7 @@ public interface JsExtensions {
);
}
default byte[] aesEncodeToByteArray(String data, String key, String transformation) {
default byte[] aesEncodeToByteArray(String data, String key, String transformation) throws Exception {
return aesEncodeToByteArray(data, key, transformation, "");
}
@ -360,7 +360,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
default String aesEncodeToString(String data, String key, String transformation, String iv) {
default String aesEncodeToString(String data, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesEncodeToByteArray(data, key, transformation, iv);
if (bytes == null) {
return "";
@ -368,7 +368,7 @@ public interface JsExtensions {
return new String(bytes);
}
default String aesEncodeToString(String str, String key, String transformation) {
default String aesEncodeToString(String str, String key, String transformation) throws Exception {
return aesEncodeToString(str, key, transformation, "");
}
@ -380,7 +380,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation, String iv) {
default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation, String iv) throws Exception {
return EncoderUtils.INSTANCE.encryptAES2Base64(
data.getBytes(StandardCharsets.UTF_8),
key.getBytes(StandardCharsets.UTF_8),
@ -389,7 +389,7 @@ public interface JsExtensions {
);
}
default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation) {
default byte[] aesEncodeToBase64ByteArray(String data, String key, String transformation) throws Exception {
return aesEncodeToBase64ByteArray(data, key, transformation, "");
}
@ -401,7 +401,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式
* @param iv ECB模式的偏移向量
*/
default String aesEncodeToBase64String(String data, String key, String transformation, String iv) {
default String aesEncodeToBase64String(String data, String key, String transformation, String iv) throws Exception {
byte[] bytes = aesEncodeToBase64ByteArray(data, key, transformation, iv);
if (bytes == null) {
return "";
@ -409,7 +409,7 @@ public interface JsExtensions {
return new String(bytes);
}
default String aesEncodeToBase64String(String str, String key, String transformation) {
default String aesEncodeToBase64String(String str, String key, String transformation) throws Exception {
return aesEncodeToBase64String(str, key, transformation, "");
}
}

@ -0,0 +1,166 @@
package xyz.fycz.myreader.model.third3
import android.util.Base64
import android.util.Log
import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.analyzeRule.JsExtensions
import xyz.fycz.myreader.util.utils.EncoderUtils
import xyz.fycz.myreader.util.utils.GSON
import xyz.fycz.myreader.util.utils.fromJsonObject
import javax.script.SimpleBindings
/**
* 可在js里调用,source.xxx()
*/
@Suppress("unused")
abstract class BaseSource : JsExtensions {
open var concurrentRate: String? = null // 并发率
open var loginUrl: String? = null // 登录地址
//var loginUi: String? // 登录UI
open var header: String? = null // 请求头
open fun getTag(): String = ""
open fun getKey(): String = ""
/*fun loginUi(): List<RowUi>? {
return GSON.fromJsonArray(loginUi)
}*/
fun getLoginJs(): String? {
val loginJs = loginUrl
return when {
loginJs == null -> null
loginJs.startsWith("@js:") -> loginJs.substring(4)
loginJs.startsWith("<js>") ->
loginJs.substring(4, loginJs.lastIndexOf("<"))
else -> loginJs
}
}
fun login() {
getLoginJs()?.let {
evalJS(it)
}
}
/**
* 解析header规则
*/
fun getHeaderMap(hasLoginHeader: Boolean = false) = HashMap<String, String>().apply {
this[APPCONST.UA_NAME] = APPCONST.DEFAULT_USER_AGENT
header?.let {
GSON.fromJsonObject<Map<String, String>>(
when {
it.startsWith("@js:", true) ->
evalJS(it.substring(4)).toString()
it.startsWith("<js>", true) ->
evalJS(it.substring(4, it.lastIndexOf("<"))).toString()
else -> it
}
)?.let { map ->
putAll(map)
}
}
if (hasLoginHeader) {
getLoginHeaderMap()?.let {
putAll(it)
}
}
}
/**
* 获取用于登录的头部信息
*/
fun getLoginHeader(): String? {
return CacheManager.get("loginHeader_${getKey()}")
}
fun getLoginHeaderMap(): Map<String, String>? {
val cache = getLoginHeader() ?: return null
return GSON.fromJsonObject(cache)
}
/**
* 保存登录头部信息,map格式,访问时自动添加
*/
fun putLoginHeader(header: String) {
CacheManager.put("loginHeader_${getKey()}", header)
}
fun removeLoginHeader() {
CacheManager.delete("loginHeader_${getKey()}")
}
/**
* 获取用户信息,可以用来登录
* 用户信息采用aes加密存储
*/
fun getLoginInfo(): String? {
try {
val key = APPCONST.androidId.encodeToByteArray(0, 8)
val cache = CacheManager.get("userInfo_${getKey()}") ?: return null
val encodeBytes = Base64.decode(cache, Base64.DEFAULT)
val decodeBytes = EncoderUtils.decryptAES(encodeBytes, key)
?: return null
return String(decodeBytes)
} catch (e: Exception) {
Log.e("BaseSource","" + e.localizedMessage)
return null
}
}
fun getLoginInfoMap(): Map<String, String>? {
return GSON.fromJsonObject(getLoginInfo())
}
/**
* 保存用户信息,aes加密
*/
fun putLoginInfo(info: String): Boolean {
return try {
val key = (APPCONST.androidId).encodeToByteArray(0, 8)
val encodeBytes = EncoderUtils.encryptAES(info.toByteArray(), key)
val encodeStr = Base64.encodeToString(encodeBytes, Base64.DEFAULT)
CacheManager.put("userInfo_${getKey()}", encodeStr)
true
} catch (e: Exception) {
Log.e("BaseSource","" + e.localizedMessage)
false
}
}
fun removeLoginInfo() {
CacheManager.delete("userInfo_${getKey()}")
}
fun setVariable(variable: String?) {
if (variable != null) {
CacheManager.put("sourceVariable_${getKey()}", variable)
} else {
CacheManager.delete("sourceVariable_${getKey()}")
}
}
fun getVariable(): String? {
return CacheManager.get("sourceVariable_${getKey()}")
}
/**
* 执行JS
*/
@Throws(Exception::class)
fun evalJS(jsStr: String, bindingsConfig: SimpleBindings.() -> Unit = {}): Any? {
val bindings = SimpleBindings()
bindings.apply(bindingsConfig)
bindings["java"] = this
bindings["source"] = this
bindings["baseUrl"] = getKey()
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
return APPCONST.SCRIPT_ENGINE.eval(jsStr, bindings)
}
}

@ -13,6 +13,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter
import xyz.fycz.myreader.greendao.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.BaseSource
import xyz.fycz.myreader.util.utils.*
import java.net.URL
import java.util.*
@ -27,7 +28,7 @@ import kotlin.collections.HashMap
@Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate")
class AnalyzeRule(
val ruleData: RuleDataInterface,
private val source: BookSource? = null
private val source: BaseSource? = null
) : JsExtensions {
var book = if (ruleData is Book) ruleData else null
@ -650,7 +651,7 @@ class AnalyzeRule(
return SCRIPT_ENGINE.eval(jsStr, bindings)
}
override fun getSource(): BookSource? {
override fun getSource(): BaseSource? {
return source
}

@ -12,6 +12,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter
import xyz.fycz.myreader.greendao.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.BaseSource
import xyz.fycz.myreader.model.third3.ConcurrentException
import xyz.fycz.myreader.model.third3.http.*
import xyz.fycz.myreader.util.utils.*
@ -36,7 +37,7 @@ class AnalyzeUrl(
val speakText: String? = null,
val speakSpeed: Int? = null,
var baseUrl: String = "",
private val source: BookSource? = null,
private val source: BaseSource? = null,
private val ruleData: RuleDataInterface? = null,
private val chapter: Chapter? = null,
headerMapF: Map<String, String>? = null,
@ -284,10 +285,10 @@ class AnalyzeUrl(
return null
}
val rateIndex = concurrentRate.indexOf("/")
var fetchRecord = concurrentRecordMap[source.sourceUrl]
var fetchRecord = concurrentRecordMap[source.getKey()]
if (fetchRecord == null) {
fetchRecord = ConcurrentRecord(rateIndex > 0, System.currentTimeMillis(), 1)
concurrentRecordMap[source.sourceUrl] = fetchRecord
concurrentRecordMap[source.getKey()] = fetchRecord
return fetchRecord
}
val waitTime: Int = synchronized(fetchRecord) {
@ -352,7 +353,7 @@ class AnalyzeUrl(
return StrResponse(url, StringUtils.byteToHexString(getByteArrayAwait()))
}
val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl)
setCookie(source?.getKey())
val strResponse: StrResponse
if (this.useWebView && useWebView) {
strResponse = when (method) {
@ -369,7 +370,7 @@ class AnalyzeUrl(
BackstageWebView(
url = url,
html = body,
tag = source?.sourceUrl,
tag = source?.getKey(),
javaScript = webJs ?: jsStr,
sourceRegex = sourceRegex,
headerMap = headerMap
@ -377,7 +378,7 @@ class AnalyzeUrl(
}
else -> BackstageWebView(
url = url,
tag = source?.sourceUrl,
tag = source?.getKey(),
javaScript = webJs ?: jsStr,
sourceRegex = sourceRegex,
headerMap = headerMap
@ -419,7 +420,7 @@ class AnalyzeUrl(
*/
suspend fun getResponseAwait(): Response {
val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl)
setCookie(source?.getKey())
@Suppress("BlockingMethodInNonBlockingContext")
val response = getProxyClient(proxy).newCallResponse(retry) {
addHeaders(headerMap)
@ -450,7 +451,7 @@ class AnalyzeUrl(
*/
suspend fun getByteArrayAwait(): ByteArray {
val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl)
setCookie(source?.getKey())
@Suppress("BlockingMethodInNonBlockingContext")
val byteArray = getProxyClient(proxy).newCallResponseBody(retry) {
addHeaders(headerMap)
@ -527,7 +528,7 @@ class AnalyzeUrl(
return method == RequestMethod.POST
}
override fun getSource(): BookSource? {
override fun getSource(): BaseSource? {
return source
}

@ -15,6 +15,7 @@ import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.greendao.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.BaseSource
import xyz.fycz.myreader.model.third3.http.*
import xyz.fycz.myreader.util.ZipUtils
import xyz.fycz.myreader.util.utils.*
@ -40,7 +41,7 @@ interface JsExtensions {
val TAG: String?
get() = JsExtensions::class.simpleName
fun getSource(): BookSource?
fun getSource(): BaseSource?
/**
* 访问网络,返回String
@ -487,7 +488,7 @@ interface JsExtensions {
Debug.log(it.sourceUrl, msg)
} ?: Debug.log(msg)*/
if (App.isDebug()) {
Log.d(TAG + "-" + getSource()?.sourceUrl, msg)
Log.d(TAG + "-" + getSource()?.getKey(), msg)
}
return msg
}

@ -67,7 +67,7 @@ object BookChapterList {
mUrl = nextUrl,
source = bookSource,
ruleData = book,
//headerMapF = bookSource.getHeaderMap()
headerMapF = bookSource.getHeaderMap()
).getStrResponseAwait().body?.let { nextBody ->
chapterData = analyzeChapterList(
scope, book, nextUrl, nextUrl,
@ -89,7 +89,7 @@ object BookChapterList {
mUrl = urlStr,
source = bookSource,
ruleData = book,
//headerMapF = bookSource.getHeaderMap()
headerMapF = bookSource.getHeaderMap()
)
val res = analyzeUrl.getStrResponseAwait()
analyzeChapterList(

@ -76,7 +76,7 @@ object BookContent {
mUrl = nextUrl,
source = bookSource,
ruleData = book,
//headerMapF = bookSource.getHeaderMap()
headerMapF = bookSource.getHeaderMap()
).getStrResponseAwait()
res.body?.let { nextBody ->
contentData = analyzeContent(
@ -99,7 +99,7 @@ object BookContent {
mUrl = urlStr,
source = bookSource,
ruleData = book,
//headerMapF = bookSource.getHeaderMap()
headerMapF = bookSource.getHeaderMap()
)
val res = analyzeUrl.getStrResponseAwait()
analyzeContent(

@ -144,7 +144,7 @@ object BookList {
baseUrl,
false
)
if (book.name.isNotBlank()) {
if (book.name.isNullOrBlank()) {
//return book.toSearchBook()
return book
}

@ -45,7 +45,7 @@ object WebBook {
key = key,
page = page,
baseUrl = bookSource.sourceUrl,
//headerMapF = bookSource.getHeaderMap(true),
headerMapF = bookSource.getHeaderMap(true),
source = bookSource,
ruleData = variableBook,
)
@ -97,7 +97,7 @@ object WebBook {
baseUrl = bookSource.sourceUrl,
source = bookSource,
ruleData = variableBook,
//headerMapF = bookSource.getHeaderMap(true)
headerMapF = bookSource.getHeaderMap(true)
)
var res = analyzeUrl.getStrResponseAwait()
//检测书源是否已登录
@ -155,7 +155,7 @@ object WebBook {
baseUrl = bookSource.sourceUrl,
source = bookSource,
ruleData = book,
//headerMapF = bookSource.getHeaderMap(true)
headerMapF = bookSource.getHeaderMap(true)
)
var res = analyzeUrl.getStrResponseAwait()
//检测书源是否已登录
@ -212,6 +212,7 @@ object WebBook {
baseUrl = book.infoUrl,
source = bookSource,
ruleData = book,
headerMapF = bookSource.getHeaderMap(true)
)
var res = analyzeUrl.getStrResponseAwait()
//检测书源是否已登录
@ -277,12 +278,12 @@ object WebBook {
source = bookSource,
ruleData = book,
chapter = bookChapter,
headerMapF = bookSource.getHeaderMap(true)
)
/*var res = analyzeUrl.getStrResponseAwait(
var res = analyzeUrl.getStrResponseAwait(
jsStr = bookSource.contentRule.webJs,
sourceRegex = bookSource.contentRule.sourceRegex
)*/
var res = analyzeUrl.getStrResponseAwait()
)
//检测书源是否已登录
bookSource.loginCheckJs?.let { checkJs ->
if (checkJs.isNotBlank()) {

@ -93,7 +93,7 @@ class SearchAdapter(
if (payload == null) {
bind(binding, item)
} else {
val books = mBooks.getValues(item)
val books = mBooks.getValues(item) ?: arrayListOf()
books2SearchBookBean(item, books)
bindChange(binding, item, payload)
}

@ -37,6 +37,7 @@ object EncoderUtils {
fun base64Encode(str: String, flags: Int = Base64.NO_WRAP): String? {
return Base64.encodeToString(str.toByteArray(), flags)
}
//////////AES Start
/**
@ -44,16 +45,18 @@ object EncoderUtils {
*
* @param data The data.
* @param key The key.
* @param transformation The name of the transformation, e.g., *DES/CBC/PKCS5Padding*.
* @param transformation The name of the transformation,
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @return the Base64-encode bytes of AES encryption
*/
@Throws(Exception::class)
fun encryptAES2Base64(
data: ByteArray?,
key: ByteArray?,
transformation: String?,
iv: ByteArray?
transformation: String? = "DES/ECB/PKCS5Padding",
iv: ByteArray? = null
): ByteArray? {
return Base64.encode(encryptAES(data, key, transformation, iv), Base64.NO_WRAP)
}
@ -63,16 +66,18 @@ object EncoderUtils {
*
* @param data The data.
* @param key The key.
* @param transformation The name of the transformation, e.g., *DES/CBC/PKCS5Padding*.
* @param transformation The name of the transformation,
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @return the bytes of AES encryption
*/
@Throws(Exception::class)
fun encryptAES(
data: ByteArray?,
key: ByteArray?,
transformation: String?,
iv: ByteArray?
transformation: String? = "DES/ECB/PKCS5Padding",
iv: ByteArray? = null
): ByteArray? {
return symmetricTemplate(data, key, "AES", transformation!!, iv, true)
}
@ -83,16 +88,18 @@ object EncoderUtils {
*
* @param data The data.
* @param key The key.
* @param transformation The name of the transformation, e.g., *DES/CBC/PKCS5Padding*.
* @param transformation The name of the transformation,
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @return the bytes of AES decryption for Base64-encode bytes
*/
@Throws(Exception::class)
fun decryptBase64AES(
data: ByteArray?,
key: ByteArray?,
transformation: String?,
iv: ByteArray?
transformation: String = "DES/ECB/PKCS5Padding",
iv: ByteArray? = null
): ByteArray? {
return decryptAES(Base64.decode(data, Base64.NO_WRAP), key, transformation, iv)
}
@ -102,18 +109,20 @@ object EncoderUtils {
*
* @param data The data.
* @param key The key.
* @param transformation The name of the transformation, e.g., *DES/CBC/PKCS5Padding*.
* @param transformation The name of the transformation,
* 加密算法/加密模式/填充类型, *DES/CBC/PKCS5Padding*.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @return the bytes of AES decryption
*/
@Throws(Exception::class)
fun decryptAES(
data: ByteArray?,
key: ByteArray?,
transformation: String?,
iv: ByteArray?
transformation: String = "DES/ECB/PKCS5Padding",
iv: ByteArray? = null
): ByteArray? {
return symmetricTemplate(data, key, "AES", transformation!!, iv, false)
return symmetricTemplate(data, key, "AES", transformation, iv, false)
}
@ -123,11 +132,15 @@ object EncoderUtils {
* @param data The data.
* @param key The key.
* @param algorithm The name of algorithm.
* @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
* @param transformation The name of the transformation,
* 加密算法/加密模式/填充类型, <i>DES/CBC/PKCS5Padding</i>.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @param isEncrypt True to encrypt, false otherwise.
* @return the bytes of symmetric encryption or decryption
*/
@Suppress("SameParameterValue")
@Throws(Exception::class)
private fun symmetricTemplate(
data: ByteArray?,
key: ByteArray?,
@ -136,23 +149,18 @@ object EncoderUtils {
iv: ByteArray?,
isEncrypt: Boolean
): ByteArray? {
return if (data == null || data.isEmpty() || key == null || key.isEmpty()) null else try {
return if (data == null || data.isEmpty() || key == null || key.isEmpty()) null
else {
val keySpec = SecretKeySpec(key, algorithm)
val cipher = Cipher.getInstance(transformation)
val mode = if (isEncrypt) Cipher.ENCRYPT_MODE else Cipher.DECRYPT_MODE
if (iv == null || iv.isEmpty()) {
cipher.init(if (isEncrypt) Cipher.ENCRYPT_MODE else Cipher.DECRYPT_MODE, keySpec)
cipher.init(mode, keySpec)
} else {
val params: AlgorithmParameterSpec = IvParameterSpec(iv)
cipher.init(
if (isEncrypt) Cipher.ENCRYPT_MODE else Cipher.DECRYPT_MODE,
keySpec,
params
)
cipher.init(mode, keySpec, params)
}
cipher.doFinal(data)
} catch (e: Throwable) {
e.printStackTrace()
null
}
}

@ -6,6 +6,9 @@ import java.util.regex.Pattern
@Suppress("RegExpRedundantEscape")
object HtmlFormatter {
private val nbspRegex = "(&nbsp;)+".toRegex()
private val espRegex = "(&ensp;|&emsp;)".toRegex()
private val noPrintRegex = "(&thinsp;|&zwnj;|&zwj;)".toRegex()
private val wrapHtmlRegex = "</?(?:div|p|br|hr|h\\d|article|dd|dl)[^>]*>".toRegex()
private val commentRegex = "<!--[^>]*-->".toRegex() //注释
private val notImgHtmlRegex = "</?(?!img)[a-zA-Z]+(?=[ >])[^<>]*>".toRegex()
@ -17,7 +20,10 @@ object HtmlFormatter {
fun format(html: String?, otherRegex: Regex = otherHtmlRegex): String {
html ?: return ""
return html.replace(wrapHtmlRegex, "\n")
return html.replace(nbspRegex, " ")
.replace(espRegex, " ")
.replace(noPrintRegex, "")
.replace(wrapHtmlRegex, "\n")
.replace(commentRegex, "")
.replace(otherRegex, "")
.replace("\\s*\\n+\\s*".toRegex(), "\n  ")

@ -16,7 +16,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class BiJianReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "http://www.bjcan.com";
public static final String NOVEL_SEARCH = "http://www.bjcan.com/home/search/index.html?keyword={key}";

@ -20,9 +20,9 @@ import java.util.ArrayList;
public class BiQuGe44ReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
// public static final String NAME_SPACE = "http://www.wqge.net";
public static final String NAME_SPACE = "https://www.wqge.cc";
public static final String NOVEL_SEARCH = "https://www.wqge.cc/modules/article/search.php?searchkey={key}";
public static final String NAME_SPACE = "http://www.wqge.net";
// public static final String NAME_SPACE = "https://www.wqge.cc";
public static final String NOVEL_SEARCH = "https://www.wqge.net/modules/article/search.php?searchkey={key}";
public static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "utf-8";

@ -18,7 +18,7 @@ import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
@Deprecated
public class EWenXueReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "http://ewenxue.org";
public static final String NOVEL_SEARCH = "http://ewenxue.org/search.htm?keyword={key}";

@ -21,7 +21,7 @@ import java.util.regex.Pattern;
/**
* 风月小说网html解析工具
*/
@Deprecated
public class FYReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://novel.fycz.xyz";
public static final String NOVEL_SEARCH = "https://novel.fycz.xyz/search.html?keyword={key}";

@ -17,7 +17,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class HongChenReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.zuxs.net";
public static final String NOVEL_SEARCH = "https://www.zuxs.net/search.php?key={key}";

@ -74,7 +74,7 @@ public class PiaoTianReadCrawler extends BaseReadCrawler implements BookInfoCraw
ArrayList<Chapter> chapters = new ArrayList<>();
Document doc = Jsoup.parse(html);
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content");
Element ul = doc.getElementsByClass("chapterlist").get(1);
Element ul = doc.getElementsByClass("ttname").first();
Elements elementsByTag = ul.getElementsByTag("a");
int i = 0;
for (int j = 0; j < elementsByTag.size(); j++) {

@ -21,6 +21,7 @@ import java.util.ArrayList;
* @author fengyue
* @date 2020/5/19 19:50
*/
@Deprecated
public class PinShuReadCrawler2 extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.vodtw.la";
public static final String NOVEL_SEARCH = "https://www.vodtw.la/search.html";

@ -17,7 +17,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class ShiGuangReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.youxs.org";
public static final String NOVEL_SEARCH = "https://www.youxs.org/search.php?key={key}";

@ -24,8 +24,8 @@ import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
public class ShuHaiGeReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.xinshuhaige.org";
public static final String NOVEL_SEARCH = "https://www.xinshuhaige.org/search.html,searchkey={key}&searchtype=all";
public static final String NAME_SPACE = "https://www.xinshuhaige.cc";
public static final String NOVEL_SEARCH = "https://www.xinshuhaige.cc/search.html,searchkey={key}&searchtype=all";
public static final String CHARSET = "utf-8";
public static final String SEARCH_CHARSET = "utf-8";
@ -56,8 +56,7 @@ public class ShuHaiGeReadCrawler extends BaseReadCrawler implements BookInfoCraw
@Override
public Map<String, String> getHeaders() {
String cookie = "Hm_lvt_46329db612a10d9ae3a668a40c152e0e=1612793811,1612795781,1613200980,1613218588; "
+ "__cfduid=d0ebd0275436b7b0c3ccf4c9eb7394abd1619231977 ";
String cookie = "Hm_lvt_7729c158621a96ffef4197e08613177a=1642731311; Hm_lpvt_7729c158621a96ffef4197e08613177a=1642731315";
Map<String, String> headers = new HashMap<>();
headers.put("Cookie", cookie);
return headers;

@ -22,8 +22,8 @@ import java.util.ArrayList;
*/
public class TianLaiReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.23txt.com";
public static final String NOVEL_SEARCH = "https://www.23txt.com/search.php?q={key}";
public static final String NAME_SPACE = "https://xs.23sk.com";
public static final String NOVEL_SEARCH = "https://xs.23sk.com/search.php?q={key}";
public static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "utf-8";

@ -16,7 +16,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class XBiQuGeReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.xquge.com";
public static final String NOVEL_SEARCH = "https://www.xquge.com/search?keyword={key}&sign=";

@ -20,8 +20,8 @@ import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
public class XS7ReadCrawler2 extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.xs7.co";
public static final String NOVEL_SEARCH = "https://www.xs7.co/modules/article/search.php?searchkey={key}&submit=%CB%D1%CB%F7";
public static final String NAME_SPACE = "https://www.xs7.la";
public static final String NOVEL_SEARCH = "https://www.xs7.la/modules/article/search.php?searchkey={key}&submit=%CB%D1%CB%F7";
public static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "GBK";

@ -17,7 +17,7 @@ import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class XiaGuReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.xiagu.org";
public static final String NOVEL_SEARCH = "https://www.xiagu.org/search/?keyword={key}&t=0";

@ -20,8 +20,8 @@ import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
public class ZW37ReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
private static final String NAME_SPACE = "https://www.37zww.net";
private static final String NOVEL_SEARCH = "https://www.37zww.net/modules/article/search.php?searchtype=articlename&searchkey={key}";
private static final String NAME_SPACE = "https://www.777zw.net";
private static final String NOVEL_SEARCH = "https://www.777zw.net/modules/article/search.php?searchtype=articlename&searchkey={key}";
private static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "GBK";

@ -18,8 +18,8 @@ import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
public class ZaiShuYuanReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.zhaishuyuan.com";
public static final String NOVEL_SEARCH = "https://www.zhaishuyuan.com/search/,key={key}";
public static final String NAME_SPACE = "https://www.zhaishuyuan.org";
public static final String NOVEL_SEARCH = "https://www.zhaishuyuan.org/search/,searchkey={key}&submit=";
public static final String CHARSET = "gbk";
public static final String SEARCH_CHARSET = "gbk";

@ -17,7 +17,7 @@ import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
import java.util.ArrayList;
@Deprecated
public class ZuoPinReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "http://zuopinj.com";
public static final String NOVEL_SEARCH = "http://so.zuopinj.com/search/index.php,tbname=bookname&show=title&tempid=3&keyboard={key}";

Loading…
Cancel
Save