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 //JS
//noinspection GradleDependency //noinspection GradleDependency
implementation 'com.github.gedoor:rhino-android:1.3' implementation 'com.github.gedoor:rhino-android:1.6'
//XXPermissions //XXPermissions
implementation 'com.github.getActivity:XXPermissions:11.2' implementation 'com.github.getActivity:XXPermissions:11.2'

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

@ -5,6 +5,7 @@ import android.os.Parcelable;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson; 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.InfoRuleConvert;
import xyz.fycz.myreader.greendao.convert.SearchRuleConvert; import xyz.fycz.myreader.greendao.convert.SearchRuleConvert;
import xyz.fycz.myreader.greendao.convert.TocRuleConvert; import xyz.fycz.myreader.greendao.convert.TocRuleConvert;
import xyz.fycz.myreader.model.third3.BaseSource;
import static xyz.fycz.myreader.util.utils.StringUtils.stringEquals; 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 * @date 2021/2/8 17:37
*/ */
@Entity @Entity
public class BookSource implements Parcelable, Cloneable { public class BookSource extends BaseSource implements Parcelable, Cloneable {
//基本信息 //基本信息
@Id @Id
private String sourceUrl; private String sourceUrl;
@ -422,4 +424,31 @@ public class BookSource implements Parcelable, Cloneable {
public void setConcurrentRate(String concurrentRate) { public void setConcurrentRate(String concurrentRate) {
this.concurrentRate = 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 content;
private String contentBaseUrl; private String contentBaseUrl;
private String contentUrlNext; private String contentUrlNext;
private String webJs;
private String sourceRegex;
private String replaceRegex; private String replaceRegex;
protected ContentRule(Parcel in) { protected ContentRule(Parcel in) {
content = in.readString(); content = in.readString();
contentBaseUrl = in.readString(); contentBaseUrl = in.readString();
contentUrlNext = in.readString(); contentUrlNext = in.readString();
webJs = in.readString();
sourceRegex = in.readString();
replaceRegex = in.readString(); replaceRegex = in.readString();
} }
@ -33,6 +37,8 @@ public class ContentRule implements Parcelable {
dest.writeString(content); dest.writeString(content);
dest.writeString(contentBaseUrl); dest.writeString(contentBaseUrl);
dest.writeString(contentUrlNext); dest.writeString(contentUrlNext);
dest.writeString(webJs);
dest.writeString(sourceRegex);
dest.writeString(replaceRegex); dest.writeString(replaceRegex);
} }
@ -62,6 +68,8 @@ public class ContentRule implements Parcelable {
return stringEquals(content, that.content) && return stringEquals(content, that.content) &&
stringEquals(contentBaseUrl, that.contentBaseUrl) && stringEquals(contentBaseUrl, that.contentBaseUrl) &&
stringEquals(contentUrlNext, that.contentUrlNext) && stringEquals(contentUrlNext, that.contentUrlNext) &&
stringEquals(webJs, that.webJs) &&
stringEquals(sourceRegex, that.sourceRegex) &&
stringEquals(replaceRegex, that.replaceRegex); stringEquals(replaceRegex, that.replaceRegex);
} }
@ -93,6 +101,22 @@ public class ContentRule implements Parcelable {
this.contentUrlNext = contentUrlNext; 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() { public String getReplaceRegex() {
return replaceRegex; return replaceRegex;
} }

@ -252,7 +252,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式 * @param transformation AES加密的方式
* @param iv ECB模式的偏移向量 * @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( return EncoderUtils.INSTANCE.decryptAES(
str.getBytes(StandardCharsets.UTF_8), 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, ""); return aesDecodeToByteArray(str, key, transformation, "");
} }
@ -275,7 +275,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量 * @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); byte[] bytes = aesDecodeToByteArray(str, key, transformation, iv);
if (bytes == null) { if (bytes == null) {
return ""; return "";
@ -283,7 +283,7 @@ public interface JsExtensions {
return new String(bytes); 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, ""); return aesDecodeToString(str, key, transformation, "");
} }
@ -296,7 +296,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量 * @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( return EncoderUtils.INSTANCE.decryptBase64AES(
str.getBytes(StandardCharsets.UTF_8), str.getBytes(StandardCharsets.UTF_8),
key.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, ""); return aesBase64DecodeToByteArray(str, key, transformation, "");
} }
@ -319,7 +319,7 @@ public interface JsExtensions {
* @param iv ECB模式的偏移向量 * @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); byte[] bytes = aesBase64DecodeToByteArray(str, key, transformation, iv);
if (bytes == null) { if (bytes == null) {
return ""; return "";
@ -327,7 +327,7 @@ public interface JsExtensions {
return new String(bytes); 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, ""); return aesBase64DecodeToString(str, key, transformation, "");
} }
@ -339,7 +339,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式 * @param transformation AES加密的方式
* @param iv ECB模式的偏移向量 * @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( return EncoderUtils.INSTANCE.encryptAES(
data.getBytes(StandardCharsets.UTF_8), data.getBytes(StandardCharsets.UTF_8),
key.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, ""); return aesEncodeToByteArray(data, key, transformation, "");
} }
@ -360,7 +360,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式 * @param transformation AES加密的方式
* @param iv ECB模式的偏移向量 * @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); byte[] bytes = aesEncodeToByteArray(data, key, transformation, iv);
if (bytes == null) { if (bytes == null) {
return ""; return "";
@ -368,7 +368,7 @@ public interface JsExtensions {
return new String(bytes); 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, ""); return aesEncodeToString(str, key, transformation, "");
} }
@ -380,7 +380,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式 * @param transformation AES加密的方式
* @param iv ECB模式的偏移向量 * @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( return EncoderUtils.INSTANCE.encryptAES2Base64(
data.getBytes(StandardCharsets.UTF_8), data.getBytes(StandardCharsets.UTF_8),
key.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, ""); return aesEncodeToBase64ByteArray(data, key, transformation, "");
} }
@ -401,7 +401,7 @@ public interface JsExtensions {
* @param transformation AES加密的方式 * @param transformation AES加密的方式
* @param iv ECB模式的偏移向量 * @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); byte[] bytes = aesEncodeToBase64ByteArray(data, key, transformation, iv);
if (bytes == null) { if (bytes == null) {
return ""; return "";
@ -409,7 +409,7 @@ public interface JsExtensions {
return new String(bytes); 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, ""); 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.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore import xyz.fycz.myreader.greendao.service.CookieStore
import xyz.fycz.myreader.model.third3.BaseSource
import xyz.fycz.myreader.util.utils.* import xyz.fycz.myreader.util.utils.*
import java.net.URL import java.net.URL
import java.util.* import java.util.*
@ -27,7 +28,7 @@ import kotlin.collections.HashMap
@Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate") @Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate")
class AnalyzeRule( class AnalyzeRule(
val ruleData: RuleDataInterface, val ruleData: RuleDataInterface,
private val source: BookSource? = null private val source: BaseSource? = null
) : JsExtensions { ) : JsExtensions {
var book = if (ruleData is Book) ruleData else null var book = if (ruleData is Book) ruleData else null
@ -650,7 +651,7 @@ class AnalyzeRule(
return SCRIPT_ENGINE.eval(jsStr, bindings) return SCRIPT_ENGINE.eval(jsStr, bindings)
} }
override fun getSource(): BookSource? { override fun getSource(): BaseSource? {
return source 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.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore 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.ConcurrentException
import xyz.fycz.myreader.model.third3.http.* import xyz.fycz.myreader.model.third3.http.*
import xyz.fycz.myreader.util.utils.* import xyz.fycz.myreader.util.utils.*
@ -36,7 +37,7 @@ class AnalyzeUrl(
val speakText: String? = null, val speakText: String? = null,
val speakSpeed: Int? = null, val speakSpeed: Int? = null,
var baseUrl: String = "", var baseUrl: String = "",
private val source: BookSource? = null, private val source: BaseSource? = null,
private val ruleData: RuleDataInterface? = null, private val ruleData: RuleDataInterface? = null,
private val chapter: Chapter? = null, private val chapter: Chapter? = null,
headerMapF: Map<String, String>? = null, headerMapF: Map<String, String>? = null,
@ -284,10 +285,10 @@ class AnalyzeUrl(
return null return null
} }
val rateIndex = concurrentRate.indexOf("/") val rateIndex = concurrentRate.indexOf("/")
var fetchRecord = concurrentRecordMap[source.sourceUrl] var fetchRecord = concurrentRecordMap[source.getKey()]
if (fetchRecord == null) { if (fetchRecord == null) {
fetchRecord = ConcurrentRecord(rateIndex > 0, System.currentTimeMillis(), 1) fetchRecord = ConcurrentRecord(rateIndex > 0, System.currentTimeMillis(), 1)
concurrentRecordMap[source.sourceUrl] = fetchRecord concurrentRecordMap[source.getKey()] = fetchRecord
return fetchRecord return fetchRecord
} }
val waitTime: Int = synchronized(fetchRecord) { val waitTime: Int = synchronized(fetchRecord) {
@ -352,7 +353,7 @@ class AnalyzeUrl(
return StrResponse(url, StringUtils.byteToHexString(getByteArrayAwait())) return StrResponse(url, StringUtils.byteToHexString(getByteArrayAwait()))
} }
val concurrentRecord = fetchStart() val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl) setCookie(source?.getKey())
val strResponse: StrResponse val strResponse: StrResponse
if (this.useWebView && useWebView) { if (this.useWebView && useWebView) {
strResponse = when (method) { strResponse = when (method) {
@ -369,7 +370,7 @@ class AnalyzeUrl(
BackstageWebView( BackstageWebView(
url = url, url = url,
html = body, html = body,
tag = source?.sourceUrl, tag = source?.getKey(),
javaScript = webJs ?: jsStr, javaScript = webJs ?: jsStr,
sourceRegex = sourceRegex, sourceRegex = sourceRegex,
headerMap = headerMap headerMap = headerMap
@ -377,7 +378,7 @@ class AnalyzeUrl(
} }
else -> BackstageWebView( else -> BackstageWebView(
url = url, url = url,
tag = source?.sourceUrl, tag = source?.getKey(),
javaScript = webJs ?: jsStr, javaScript = webJs ?: jsStr,
sourceRegex = sourceRegex, sourceRegex = sourceRegex,
headerMap = headerMap headerMap = headerMap
@ -419,7 +420,7 @@ class AnalyzeUrl(
*/ */
suspend fun getResponseAwait(): Response { suspend fun getResponseAwait(): Response {
val concurrentRecord = fetchStart() val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl) setCookie(source?.getKey())
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
val response = getProxyClient(proxy).newCallResponse(retry) { val response = getProxyClient(proxy).newCallResponse(retry) {
addHeaders(headerMap) addHeaders(headerMap)
@ -450,7 +451,7 @@ class AnalyzeUrl(
*/ */
suspend fun getByteArrayAwait(): ByteArray { suspend fun getByteArrayAwait(): ByteArray {
val concurrentRecord = fetchStart() val concurrentRecord = fetchStart()
setCookie(source?.sourceUrl) setCookie(source?.getKey())
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
val byteArray = getProxyClient(proxy).newCallResponseBody(retry) { val byteArray = getProxyClient(proxy).newCallResponseBody(retry) {
addHeaders(headerMap) addHeaders(headerMap)
@ -527,7 +528,7 @@ class AnalyzeUrl(
return method == RequestMethod.POST return method == RequestMethod.POST
} }
override fun getSource(): BookSource? { override fun getSource(): BaseSource? {
return source 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.entity.rule.BookSource
import xyz.fycz.myreader.greendao.service.CacheManager import xyz.fycz.myreader.greendao.service.CacheManager
import xyz.fycz.myreader.greendao.service.CookieStore 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.model.third3.http.*
import xyz.fycz.myreader.util.ZipUtils import xyz.fycz.myreader.util.ZipUtils
import xyz.fycz.myreader.util.utils.* import xyz.fycz.myreader.util.utils.*
@ -40,7 +41,7 @@ interface JsExtensions {
val TAG: String? val TAG: String?
get() = JsExtensions::class.simpleName get() = JsExtensions::class.simpleName
fun getSource(): BookSource? fun getSource(): BaseSource?
/** /**
* 访问网络,返回String * 访问网络,返回String
@ -487,7 +488,7 @@ interface JsExtensions {
Debug.log(it.sourceUrl, msg) Debug.log(it.sourceUrl, msg)
} ?: Debug.log(msg)*/ } ?: Debug.log(msg)*/
if (App.isDebug()) { if (App.isDebug()) {
Log.d(TAG + "-" + getSource()?.sourceUrl, msg) Log.d(TAG + "-" + getSource()?.getKey(), msg)
} }
return msg return msg
} }

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

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

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

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

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

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

@ -6,6 +6,9 @@ import java.util.regex.Pattern
@Suppress("RegExpRedundantEscape") @Suppress("RegExpRedundantEscape")
object HtmlFormatter { 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 wrapHtmlRegex = "</?(?:div|p|br|hr|h\\d|article|dd|dl)[^>]*>".toRegex()
private val commentRegex = "<!--[^>]*-->".toRegex() //注释 private val commentRegex = "<!--[^>]*-->".toRegex() //注释
private val notImgHtmlRegex = "</?(?!img)[a-zA-Z]+(?=[ >])[^<>]*>".toRegex() private val notImgHtmlRegex = "</?(?!img)[a-zA-Z]+(?=[ >])[^<>]*>".toRegex()
@ -17,7 +20,10 @@ object HtmlFormatter {
fun format(html: String?, otherRegex: Regex = otherHtmlRegex): String { fun format(html: String?, otherRegex: Regex = otherHtmlRegex): String {
html ?: return "" html ?: return ""
return html.replace(wrapHtmlRegex, "\n") return html.replace(nbspRegex, " ")
.replace(espRegex, " ")
.replace(noPrintRegex, "")
.replace(wrapHtmlRegex, "\n")
.replace(commentRegex, "") .replace(commentRegex, "")
.replace(otherRegex, "") .replace(otherRegex, "")
.replace("\\s*\\n+\\s*".toRegex(), "\n  ") .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.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class BiJianReadCrawler extends BaseReadCrawler { public class BiJianReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "http://www.bjcan.com"; 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}"; 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 class BiQuGe44ReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
// public static final String NAME_SPACE = "http://www.wqge.net"; public static final String NAME_SPACE = "http://www.wqge.net";
public static final String NAME_SPACE = "https://www.wqge.cc"; // 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 NOVEL_SEARCH = "https://www.wqge.net/modules/article/search.php?searchkey={key}";
public static final String CHARSET = "GBK"; public static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "utf-8"; 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.BaseReadCrawler;
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler; import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
@Deprecated
public class EWenXueReadCrawler extends BaseReadCrawler implements BookInfoCrawler { public class EWenXueReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "http://ewenxue.org"; public static final String NAME_SPACE = "http://ewenxue.org";
public static final String NOVEL_SEARCH = "http://ewenxue.org/search.htm?keyword={key}"; public static final String NOVEL_SEARCH = "http://ewenxue.org/search.htm?keyword={key}";

@ -21,7 +21,7 @@ import java.util.regex.Pattern;
/** /**
* 风月小说网html解析工具 * 风月小说网html解析工具
*/ */
@Deprecated
public class FYReadCrawler extends BaseReadCrawler { public class FYReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://novel.fycz.xyz"; public static final String NAME_SPACE = "https://novel.fycz.xyz";
public static final String NOVEL_SEARCH = "https://novel.fycz.xyz/search.html?keyword={key}"; 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.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class HongChenReadCrawler extends BaseReadCrawler { public class HongChenReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.zuxs.net"; public static final String NAME_SPACE = "https://www.zuxs.net";
public static final String NOVEL_SEARCH = "https://www.zuxs.net/search.php?key={key}"; 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<>(); ArrayList<Chapter> chapters = new ArrayList<>();
Document doc = Jsoup.parse(html); Document doc = Jsoup.parse(html);
String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); 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"); Elements elementsByTag = ul.getElementsByTag("a");
int i = 0; int i = 0;
for (int j = 0; j < elementsByTag.size(); j++) { for (int j = 0; j < elementsByTag.size(); j++) {

@ -21,6 +21,7 @@ import java.util.ArrayList;
* @author fengyue * @author fengyue
* @date 2020/5/19 19:50 * @date 2020/5/19 19:50
*/ */
@Deprecated
public class PinShuReadCrawler2 extends BaseReadCrawler implements BookInfoCrawler { public class PinShuReadCrawler2 extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.vodtw.la"; public static final String NAME_SPACE = "https://www.vodtw.la";
public static final String NOVEL_SEARCH = "https://www.vodtw.la/search.html"; 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.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class ShiGuangReadCrawler extends BaseReadCrawler { public class ShiGuangReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.youxs.org"; public static final String NAME_SPACE = "https://www.youxs.org";
public static final String NOVEL_SEARCH = "https://www.youxs.org/search.php?key={key}"; 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 class ShuHaiGeReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.xinshuhaige.org"; public static final String NAME_SPACE = "https://www.xinshuhaige.cc";
public static final String NOVEL_SEARCH = "https://www.xinshuhaige.org/search.html,searchkey={key}&searchtype=all"; 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 CHARSET = "utf-8";
public static final String SEARCH_CHARSET = "utf-8"; public static final String SEARCH_CHARSET = "utf-8";
@ -56,8 +56,7 @@ public class ShuHaiGeReadCrawler extends BaseReadCrawler implements BookInfoCraw
@Override @Override
public Map<String, String> getHeaders() { public Map<String, String> getHeaders() {
String cookie = "Hm_lvt_46329db612a10d9ae3a668a40c152e0e=1612793811,1612795781,1613200980,1613218588; " String cookie = "Hm_lvt_7729c158621a96ffef4197e08613177a=1642731311; Hm_lpvt_7729c158621a96ffef4197e08613177a=1642731315";
+ "__cfduid=d0ebd0275436b7b0c3ccf4c9eb7394abd1619231977 ";
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put("Cookie", cookie); headers.put("Cookie", cookie);
return headers; return headers;

@ -22,8 +22,8 @@ import java.util.ArrayList;
*/ */
public class TianLaiReadCrawler extends BaseReadCrawler { public class TianLaiReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.23txt.com"; public static final String NAME_SPACE = "https://xs.23sk.com";
public static final String NOVEL_SEARCH = "https://www.23txt.com/search.php?q={key}"; public static final String NOVEL_SEARCH = "https://xs.23sk.com/search.php?q={key}";
public static final String CHARSET = "GBK"; public static final String CHARSET = "GBK";
public static final String SEARCH_CHARSET = "utf-8"; 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.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class XBiQuGeReadCrawler extends BaseReadCrawler { public class XBiQuGeReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.xquge.com"; public static final String NAME_SPACE = "https://www.xquge.com";
public static final String NOVEL_SEARCH = "https://www.xquge.com/search?keyword={key}&sign="; 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 class XS7ReadCrawler2 extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "https://www.xs7.co"; public static final String NAME_SPACE = "https://www.xs7.la";
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 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 CHARSET = "GBK";
public static final String SEARCH_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.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.BaseReadCrawler;
@Deprecated
public class XiaGuReadCrawler extends BaseReadCrawler { public class XiaGuReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.xiagu.org"; 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"; 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 { public class ZW37ReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
private static final String NAME_SPACE = "https://www.37zww.net"; private static final String NAME_SPACE = "https://www.777zw.net";
private static final String NOVEL_SEARCH = "https://www.37zww.net/modules/article/search.php?searchtype=articlename&searchkey={key}"; private static final String NOVEL_SEARCH = "https://www.777zw.net/modules/article/search.php?searchtype=articlename&searchkey={key}";
private static final String CHARSET = "GBK"; private static final String CHARSET = "GBK";
public static final String SEARCH_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 class ZaiShuYuanReadCrawler extends BaseReadCrawler {
public static final String NAME_SPACE = "https://www.zhaishuyuan.com"; public static final String NAME_SPACE = "https://www.zhaishuyuan.org";
public static final String NOVEL_SEARCH = "https://www.zhaishuyuan.com/search/,key={key}"; public static final String NOVEL_SEARCH = "https://www.zhaishuyuan.org/search/,searchkey={key}&submit=";
public static final String CHARSET = "gbk"; public static final String CHARSET = "gbk";
public static final String SEARCH_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; import java.util.ArrayList;
@Deprecated
public class ZuoPinReadCrawler extends BaseReadCrawler implements BookInfoCrawler { public class ZuoPinReadCrawler extends BaseReadCrawler implements BookInfoCrawler {
public static final String NAME_SPACE = "http://zuopinj.com"; 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}"; public static final String NOVEL_SEARCH = "http://so.zuopinj.com/search/index.php,tbname=bookname&show=title&tempid=3&keyboard={key}";

Loading…
Cancel
Save