diff --git a/README.md b/README.md index fbb2689..231f110 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,18 @@ 风月读书,一款开源、无广告的小说阅读软件。 -成品下载:[https://fycz.lanzoui.com/ibgVdj42lbc](https://fycz.lanzoui.com/ibgVdj42lbc) +成品下载:[https://fycz.lanzoui.com/iwIrojatw9e](https://fycz.lanzoui.com/iwIrojatw9e) #### 一、关于书源 * 软件内置了25个书源如下: - * 21个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 + * 23个网络小说书源:天籁小说、笔趣阁44、品书网、笔趣阁、 全本小说、米趣小说、九桃小说、云中书库、 搜小说网、全小说网、奇奇小说、妙笔阁、 丹书铁券、小说旗、读一读网、飘天文学、 老幺小说、星星小说、时光小说、峡谷文学、 - 红尘小说 + 红尘小说、热血小说、传奇小说 * 4个实体书书源:超星图书·实体、作品集·实体、99藏书·实体、100本·实体 * 如何自行制作并添加书源. diff --git a/app/src/main/assets/updatelog.fy b/app/src/main/assets/updatelog.fy index e2eadaa..01a674c 100644 --- a/app/src/main/assets/updatelog.fy +++ b/app/src/main/assets/updatelog.fy @@ -1,6 +1,9 @@ +2020.12.12 +风月读书v1.20.121218 1、极大地优化本地书籍章节拆分速度 2、优化本地书籍文件编码识别 3、修复目录未加载时搜索闪退的bug +4、新增书源:热血小说、传奇小说 2020.12.06 风月读书v1.20.120612 diff --git a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java index a951c07..e419866 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java +++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java @@ -3,24 +3,13 @@ package xyz.fycz.myreader.application; import android.util.Log; import xyz.fycz.myreader.common.APPCONST; +import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.enums.BookSource; import xyz.fycz.myreader.enums.BookcaseStyle; -import xyz.fycz.myreader.enums.Font; -import xyz.fycz.myreader.enums.Language; -import xyz.fycz.myreader.enums.ReadStyle; -import xyz.fycz.myreader.model.backup.UserService; -import xyz.fycz.myreader.model.storage.Backup; import xyz.fycz.myreader.util.CacheHelper; -import xyz.fycz.myreader.R; -import xyz.fycz.myreader.entity.Setting; -import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; -import xyz.fycz.myreader.widget.page.PageMode; import static xyz.fycz.myreader.application.MyApplication.getVersionCode; -import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_LEATHER; -import static xyz.fycz.myreader.common.APPCONST.s; -import static xyz.fycz.myreader.widget.page.PageLoader.DEFAULT_MARGIN_WIDTH; public class SysManager { @@ -100,7 +89,7 @@ public class SysManager { public static void resetSetting() { Setting setting = getSetting(); switch (setting.getSettingVersion()) { - case 10: + case 10: default: setting.initReadStyle(); setting.setCurReadStyleIndex(1); setting.setSharedLayout(true); @@ -117,7 +106,7 @@ public class SysManager { public static void resetSource() { Setting setting = getSetting(); switch (setting.getSourceVersion()) { - case 0: + case 0: default: ReadCrawlerUtil.addReadCrawler(BookSource.miaobi, BookSource.dstq, BookSource.xs7, BookSource.du1du, BookSource.paiotian); ReadCrawlerUtil.removeReadCrawler("cangshu99"); Log.d("SourceVersion", "" + 0); @@ -125,6 +114,7 @@ public class SysManager { ReadCrawlerUtil.addReadCrawler(BookSource.laoyao, BookSource.xingxing, BookSource.shiguang, BookSource.xiagu, BookSource.hongchen); Log.d("SourceVersion", "" + 1); case 2: + ReadCrawlerUtil.addReadCrawler(BookSource.rexue, BookSource.chuanqi); Log.d("SourceVersion", "" + 2); } setting.setSourceVersion(APPCONST.SOURCE_VERSION); diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java index 6df953b..6611c43 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -12,11 +12,8 @@ public class APPCONST { public static String publicKey = "";//服务端公钥 public static String privateKey;//app私钥 - public final static String s = "11940364935628058505"; public static final String KEY = ""; - public static final String ALARM_SCHEDULE_MSG = "alarm_schedule_msg"; - public static final String FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/"; public static final String SHARE_FILE_DIR = Environment.getExternalStorageDirectory() + "/FYReader/share/"; public static final String LOG_DIR = Environment.getExternalStorageDirectory() + "/FYReader/log/"; @@ -32,7 +29,6 @@ public class APPCONST { + "book_cache"+ File.separator ; public static String HTML_CACHE_PATH = FileUtils.getCachePath() + File.separator + "html_cache"+ File.separator ; - public static final String LOADING_ERROR = "\t\t \t\t\t\t\n\n  章节内容转码失败!\n\n\t\t \t\t\t\n\n"; public static long exitTime; public static final int exitConfirmTime = 2000; @@ -61,7 +57,6 @@ public class APPCONST { public static final String FILE_NAME_SETTING = "setting"; - public static final String FILE_NAME_UPDATE_INFO = "updateInfo"; public static final String FILE_NAME_SPLASH_IMAGE = "splashImage"; public static final int SELECT_TEXT_COLOR = 201; @@ -78,11 +73,6 @@ public class APPCONST { public static final int REQUEST_READ = 1; - public static final CharSequence[] DIALOG_DOWNLOAD = { - "下载后面五十章", "下载前后五十章", - "下载后面全部章", "下载本书所有章" - }; - public static final int APP_INSTALL_CODE = 10086; public static final int SELECT_FILE_CODE = 10000; @@ -92,7 +82,7 @@ public class APPCONST { //设置版本号 public static final int SETTING_VERSION = 11; - public static final int SOURCE_VERSION = 2; + public static final int SOURCE_VERSION = 3; public static final String FORMAT_FILE_DATE = "yyyy-MM-dd"; diff --git a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java index 91e492a..2d41c10 100644 --- a/app/src/main/java/xyz/fycz/myreader/entity/Setting.java +++ b/app/src/main/java/xyz/fycz/myreader/entity/Setting.java @@ -6,15 +6,17 @@ import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.util.Log; -import xyz.fycz.myreader.application.MyApplication; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.enums.BookcaseStyle; import xyz.fycz.myreader.enums.Font; import xyz.fycz.myreader.enums.Language; import xyz.fycz.myreader.util.StringHelper; -import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.ZipUtils; import xyz.fycz.myreader.util.utils.BitmapUtil; import xyz.fycz.myreader.util.utils.FileUtils; @@ -22,19 +24,12 @@ import xyz.fycz.myreader.util.utils.GsonExtensionsKt; import xyz.fycz.myreader.util.utils.MeUtils; import xyz.fycz.myreader.widget.page.PageMode; -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_BLUE_DEEP; import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_BREEN; import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_COMMON; import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_LEATHER; import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_NIGHT; import static xyz.fycz.myreader.common.APPCONST.READ_STYLE_PROTECTED_EYE; -import static xyz.fycz.myreader.common.APPCONST.s; import static xyz.fycz.myreader.widget.page.PageLoader.DEFAULT_MARGIN_WIDTH; /** diff --git a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java index 3bf9b08..f591fed 100644 --- a/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java +++ b/app/src/main/java/xyz/fycz/myreader/enums/BookSource.java @@ -30,6 +30,8 @@ public enum BookSource { laoyao(MyApplication.getApplication().getString(R.string.read_laoyao)), xingxing(MyApplication.getApplication().getString(R.string.read_xingxing)), shiguang(MyApplication.getApplication().getString(R.string.read_shiguang)), + rexue(MyApplication.getApplication().getString(R.string.read_rexue)), + chuanqi(MyApplication.getApplication().getString(R.string.read_chuanqi)), xiagu(MyApplication.getApplication().getString(R.string.read_xiagu)), hongchen(MyApplication.getApplication().getString(R.string.read_hongchen)), chaoxing(MyApplication.getApplication().getString(R.string.read_chaoxing)), diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java index cb19859..72e093a 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java @@ -1595,7 +1595,8 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe MyApplication.runOnUiThread(() -> { MyAlertDialog.build(this) .setTitle("缓存书籍") - .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", + .setSingleChoiceItems(getResources().getStringArray(R.array.download), selectedIndex, + (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", (dialog, which) -> { switch (selectedIndex) { case 0: diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java index 99f683f..629ff60 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java @@ -2,6 +2,7 @@ package xyz.fycz.myreader.ui.activity; import android.annotation.SuppressLint; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -9,11 +10,14 @@ import android.os.Message; import android.text.Editable; import android.text.TextWatcher; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.*; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatRadioButton; import androidx.appcompat.widget.Toolbar; import androidx.recyclerview.widget.LinearLayoutManager; @@ -30,6 +34,10 @@ import xyz.fycz.myreader.application.MyApplication; import xyz.fycz.myreader.application.SysManager; import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.entity.Setting; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.ui.dialog.DialogCreator; +import xyz.fycz.myreader.ui.dialog.MultiChoiceDialog; +import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.utils.StringUtils; import xyz.fycz.myreader.webapi.callback.ResultCallback; import xyz.fycz.myreader.common.APPCONST; @@ -53,6 +61,7 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; /** @@ -122,6 +131,9 @@ public class SearchBookActivity extends BaseActivity { private Setting mSetting; + //选择禁用更新书源对话框 + private AlertDialog mDisableSourceDia; + private static String[] suggestion = {"第一序列", "大道朝天", "伏天氏", "终极斗罗", "我师兄实在太稳健了", "烂柯棋缘", "诡秘之主"}; private static String[] suggestion2 = {"不朽凡人", "圣墟", "我是至尊", "龙王传说", "太古神王", "一念永恒", "雪鹰领主", "大主宰"}; @@ -321,6 +333,66 @@ public class SearchBookActivity extends BaseActivity { } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_search, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.action_disable_source){ + showDisableSourceDia(); + } + return super.onOptionsItemSelected(item); + } + + private void showDisableSourceDia(){ + if (mDisableSourceDia != null) { + mDisableSourceDia.show(); + return; + } + + HashMap mSources = ReadCrawlerUtil.getDisableSources(); + CharSequence[] mSourcesName = new CharSequence[mSources.keySet().size()]; + boolean[] isDisables = new boolean[mSources.keySet().size()]; + int dSourceCount = 0; + int i = 0; + for (CharSequence sourceName : mSources.keySet()) { + mSourcesName[i] = sourceName; + Boolean isDisable = mSources.get(sourceName); + if (isDisable == null) isDisable = false; + if (isDisable) dSourceCount++; + isDisables[i++] = isDisable; + } + + mDisableSourceDia = new MultiChoiceDialog().create(this, "选择禁用的书源", + mSourcesName, isDisables, dSourceCount, (dialog, which) -> { + SharedPreUtils spu = SharedPreUtils.getInstance(); + StringBuilder sb = new StringBuilder(); + for (CharSequence sourceName : mSources.keySet()) { + if (!mSources.get(sourceName)) { + sb.append(BookSource.getFromName(String.valueOf(sourceName))); + sb.append(","); + } + } + if (sb.lastIndexOf(",") >= 0) sb.deleteCharAt(sb.lastIndexOf(",")); + spu.putString(getString(R.string.searchSource), sb.toString()); + }, null, new DialogCreator.OnMultiDialogListener() { + @Override + public void onItemClick(DialogInterface dialog, int which, boolean isChecked) { + mSources.put(mSourcesName[which], isChecked); + } + + @Override + public void onSelectAll(boolean isSelectAll) { + for (CharSequence sourceName : mSources.keySet()) { + mSources.put(sourceName, isSelectAll); + } + } + }); + } + /** * 初始化建议书目 */ diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java index f31ab34..68d467d 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java @@ -277,12 +277,8 @@ public abstract class BookcaseAdapter extends DragAdapter { final int[] end = new int[1]; MyAlertDialog.build(mContext) .setTitle("缓存书籍") - .setSingleChoiceItems(APPCONST.DIALOG_DOWNLOAD, selectedIndex, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - selectedIndex = which; - } - }).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", + .setSingleChoiceItems(mContext.getResources().getStringArray(R.array.download), selectedIndex, + (dialog, which) -> selectedIndex = which).setNegativeButton("取消", ((dialog, which) -> dialog.dismiss())).setPositiveButton("确定", (dialog, which) -> { switch (selectedIndex) { case 0: diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java index 2e8da9b..e7ffe30 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java @@ -141,7 +141,7 @@ public class BookcasePresenter implements BasePresenter { initBook(); isFirstRefresh = false; } - downloadAll(false); + downloadAll(false, false); } break; case 5: @@ -501,11 +501,11 @@ public class BookcasePresenter implements BasePresenter { DialogCreator.createCommonDialog(mMainActivity, "一键缓存", mMainActivity.getString(R.string.all_cathe_tip), true, (dialog, which) -> { - downloadAll(true); + downloadAll(true, true); SharedPreUtils.getInstance().putBoolean(mMainActivity.getString(R.string.isReadDownloadAllTip), true); }, null); } else { - downloadAll(true); + downloadAll(true, true); } return true; @@ -729,13 +729,14 @@ public class BookcasePresenter implements BasePresenter { /** * 缓存所有书籍 */ - private void downloadAll(boolean isDownloadAllChapters) { + private void downloadAll(boolean isDownloadAllChapters, boolean isFromUser) { if (!NetworkUtils.isNetWorkAvailable()) { ToastUtils.showWarring("无网络连接!"); return; } if (mBooks.size() == 0) { - ToastUtils.showWarring("当前书架没有任何书籍,无法一键缓存!"); + if (isFromUser) + ToastUtils.showWarring("当前书架没有任何书籍,无法一键缓存!"); return; } MyApplication.getApplication().newThread(() -> { @@ -747,7 +748,8 @@ public class BookcasePresenter implements BasePresenter { } } if (needDownloadBooks.size() == 0) { - ToastUtils.showWarring("当前书架书籍不支持/已关闭(可在设置开启)一键缓存!"); + if (isFromUser) + ToastUtils.showWarring("当前书架书籍不支持/已关闭(可在设置开启)一键缓存!"); return; } if (isDownloadAllChapters) { diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChuanQiReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChuanQiReadCrawler.java new file mode 100644 index 0000000..7cfabb3 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ChuanQiReadCrawler.java @@ -0,0 +1,204 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.Collections; + +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + + +public class ChuanQiReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "https://www.xs86.com"; + public static final String NOVEL_SEARCH = "https://www.xs86.com/search.php?key={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("txt"); + if (divContent != null) { + Elements aDiv = divContent.getElementsByTag("dd"); + StringBuilder sb = new StringBuilder(); + Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - + Integer.parseInt(o2.attr("data-id"))); + for (int i = 0; i < aDiv.size(); i++) { + Element dd = aDiv.get(i); + if (i == aDiv.size() - 1) break; + sb.append(Html.fromHtml(dd.html()).toString()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementById("listsss"); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (int j = 0; j < elementsByTag.size(); j++) { + Element a = elementsByTag.get(j); + String title = a.text(); + String url = a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(NAME_SPACE + url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + /* +
  • 大主宰 +
    +

    + 大主宰 +

    +

    作者:天蚕土豆分类:网络文学状态:连载中总字数:2497万字+

    +

    最近更新:第1598章 邪神陨落(大结局)

    +

    大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 + 无尽火域,炎帝执掌,万火焚苍穹。 + 武境之内,武祖之威

    +
    +
    + 更新时间:09-06 05:25 + 立即阅读 + 加入书架 +
    +
  • + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); +// try { + String urlType = doc.select("meta[property=og:type]").attr("content"); + if ("novel".equals(urlType)) { + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + Book book = new Book(); + book.setChapterUrl(readUrl); + getBookInfo(doc, book); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } else { + Element div = doc.getElementsByClass("result").first(); + Elements lis = div.getElementsByTag("li"); + for (Element li : lis) { + Elements as = li.getElementsByTag("a"); + Book book = new Book(); + book.setName(as.get(1).text()); + book.setAuthor(as.get(2).text()); + book.setType(as.get(3).text()); + book.setNewestChapterTitle(as.get(4).text().replace("最新章节:", "")); + book.setDesc(li.getElementsByClass("int").first().text()); + book.setUpdateDate(li.getElementsByClass("right").first().getElementsByTag("span").text()); + String imgUrl = li.getElementsByTag("img").attr("data-original"); + book.setImgUrl(imgUrl); + book.setChapterUrl(NAME_SPACE + as.get(1).attr("href")); + book.setSource(BookSource.chuanqi.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + public Book getBookInfo(Document doc, Book book) { + //小说源 + book.setSource(BookSource.chuanqi.toString()); + //图片url + String imgUrl = doc.select("meta[property=og:image]").attr("content"); + book.setImgUrl(imgUrl); + + //书名 + String title = doc.select("meta[property=og:novel:book_name]").attr("content"); + book.setName(title); + + //作者 + String author = doc.select("meta[property=og:novel:author]").attr("content"); + book.setAuthor(author); + + //更新时间 + String updateDate = doc.select("meta[property=og:novel:update_time]").attr("content"); + book.setUpdateDate(updateDate); + + //最新章节 + String newestChapterTitle = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); + book.setNewestChapterTitle(newestChapterTitle); + + //类型 + String type = doc.select("meta[property=og:novel:category]").attr("content"); + book.setType(type); + + //简介 + String desc = doc.select("meta[property=og:description]").attr("content"); + book.setDesc(desc); + return book; + + } +} diff --git a/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ReXueReadCrawler.java b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ReXueReadCrawler.java new file mode 100644 index 0000000..9fd16b0 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/ReXueReadCrawler.java @@ -0,0 +1,202 @@ +package xyz.fycz.myreader.webapi.crawler.read; + +import android.text.Html; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.Collections; + +import xyz.fycz.myreader.entity.SearchBookBean; +import xyz.fycz.myreader.enums.BookSource; +import xyz.fycz.myreader.greendao.entity.Book; +import xyz.fycz.myreader.greendao.entity.Chapter; +import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap; +import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; + + +public class ReXueReadCrawler implements ReadCrawler { + public static final String NAME_SPACE = "https://www.rexue.org"; + public static final String NOVEL_SEARCH = "https://www.rexue.org/search.php?key={key}"; + public static final String CHARSET = "UTF-8"; + public static final String SEARCH_CHARSET = "UTF-8"; + + @Override + public String getSearchLink() { + return NOVEL_SEARCH; + } + + @Override + public String getCharset() { + return CHARSET; + } + + @Override + public String getNameSpace() { + return NAME_SPACE; + } + + @Override + public Boolean isPost() { + return false; + } + + @Override + public String getSearchCharset() { + return SEARCH_CHARSET; + } + + /** + * 从html中获取章节正文 + * + * @param html + * @return + */ + public String getContentFormHtml(String html) { + Document doc = Jsoup.parse(html); + Element divContent = doc.getElementById("txt"); + if (divContent != null) { + Elements aDiv = divContent.getElementsByTag("dd"); + StringBuilder sb = new StringBuilder(); + Collections.sort(aDiv, (o1, o2) -> Integer.parseInt(o1.attr("data-id")) - + Integer.parseInt(o2.attr("data-id"))); + for (int i = 0; i < aDiv.size(); i++) { + Element dd = aDiv.get(i); + if (i == aDiv.size() - 1) break; + sb.append(Html.fromHtml(dd.html()).toString()); + sb.append("\n"); + } + String content = sb.toString(); + char c = 160; + String spaec = "" + c; + content = content.replace(spaec, " "); + return content; + } else { + return ""; + } + } + + /** + * 从html中获取章节列表 + * + * @param html + * @return + */ + public ArrayList getChaptersFromHtml(String html) { + ArrayList chapters = new ArrayList<>(); + Document doc = Jsoup.parse(html); + Element divList = doc.getElementById("listsss"); + Elements elementsByTag = divList.getElementsByTag("a"); + int i = 0; + for (int j = 0; j < elementsByTag.size(); j++) { + Element a = elementsByTag.get(j); + String title = a.text(); + String url = a.attr("href"); + Chapter chapter = new Chapter(); + chapter.setNumber(i++); + chapter.setTitle(title); + chapter.setUrl(NAME_SPACE + url); + chapters.add(chapter); + } + return chapters; + } + + /** + * 从搜索html中得到书列表 + * + * @param html + * @return + */ + /* + +
  • 大主宰 +
    +

    大主宰

    +

    作者:天蚕土豆分类:短篇文学状态:连载中总字数:2497万字+

    +

    最近更新:第1598章 邪神陨落(大结局)

    +

    大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 + 无尽火域,炎帝执掌,万火焚苍穹。 + 武境之内,武祖之威

    +
    +
    + 更新时间:09-06 06:47 + 立即阅读 + 加入书架 +
    +
  • + */ + public ConcurrentMultiValueMap getBooksFromSearchHtml(String html) { + ConcurrentMultiValueMap books = new ConcurrentMultiValueMap<>(); + Document doc = Jsoup.parse(html); +// try { + String urlType = doc.select("meta[property=og:type]").attr("content"); + if ("novel".equals(urlType)) { + String readUrl = doc.select("meta[property=og:novel:read_url]").attr("content"); + Book book = new Book(); + book.setChapterUrl(readUrl); + getBookInfo(doc, book); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } else { + Element div = doc.getElementsByClass("result").first(); + Elements lis = div.getElementsByTag("li"); + for (Element li : lis) { + Elements as = li.getElementsByTag("a"); + Book book = new Book(); + book.setName(as.get(1).text()); + book.setAuthor(as.get(2).text()); + book.setType(as.get(3).text()); + book.setNewestChapterTitle(as.get(4).text().replace("最新章节:", "")); + book.setDesc(li.getElementsByClass("int").first().text()); + book.setUpdateDate(li.getElementsByClass("right").first().getElementsByTag("span").text()); + String imgUrl = li.getElementsByTag("img").attr("data-original"); + book.setImgUrl(!imgUrl.contains("http") ? "https:" + imgUrl : imgUrl); + book.setChapterUrl(NAME_SPACE + as.get(1).attr("href")); + book.setSource(BookSource.rexue.toString()); + SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor()); + books.add(sbb, book); + } + } +// } catch (Exception e) { +// e.printStackTrace(); +// } + return books; + } + + public Book getBookInfo(Document doc, Book book) { + //小说源 + book.setSource(BookSource.rexue.toString()); + //图片url + String imgUrl = doc.select("meta[property=og:image]").attr("content"); + book.setImgUrl(imgUrl); + + //书名 + String title = doc.select("meta[property=og:novel:book_name]").attr("content"); + book.setName(title); + + //作者 + String author = doc.select("meta[property=og:novel:author]").attr("content"); + book.setAuthor(author); + + //更新时间 + String updateDate = doc.select("meta[property=og:novel:update_time]").attr("content"); + book.setUpdateDate(updateDate); + + //最新章节 + String newestChapterTitle = doc.select("meta[property=og:novel:latest_chapter_name]").attr("content"); + book.setNewestChapterTitle(newestChapterTitle); + + //类型 + String type = doc.select("meta[property=og:novel:category]").attr("content"); + book.setType(type); + + //简介 + String desc = doc.select("meta[property=og:description]").attr("content"); + book.setDesc(desc); + return book; + + } +} diff --git a/app/src/main/res/menu/menu_search.xml b/app/src/main/res/menu/menu_search.xml new file mode 100644 index 0000000..3dbf471 --- /dev/null +++ b/app/src/main/res/menu/menu_search.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 456de26..d7ee30c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -205,6 +205,8 @@ 老幺小说 星星小说 时光小说 + 热血小说 + 传奇小说 峡谷文学 红尘小说 超星图书·实体 @@ -335,4 +337,11 @@ @string/time_sort @string/book_name_sort + + + 下载后面五十章 + 下载前后五十章 + 下载后面全部章 + 下载本书所有章 + diff --git a/app/src/main/resources/crawler.properties b/app/src/main/resources/crawler.properties index 5a4f302..bb305e8 100644 --- a/app/src/main/resources/crawler.properties +++ b/app/src/main/resources/crawler.properties @@ -23,5 +23,7 @@ paiotian=xyz.fycz.myreader.webapi.crawler.read.PiaoTianReadCrawler laoyao=xyz.fycz.myreader.webapi.crawler.read.LaoYaoReadCrawler xingxing=xyz.fycz.myreader.webapi.crawler.read.XingXingReadCrawler shiguang=xyz.fycz.myreader.webapi.crawler.read.ShiGuangReadCrawler +rexue=xyz.fycz.myreader.webapi.crawler.read.ReXueReadCrawler +chuanqi=xyz.fycz.myreader.webapi.crawler.read.ChuanQiReadCrawler xiagu=xyz.fycz.myreader.webapi.crawler.read.XiaGuReadCrawler hongchen=xyz.fycz.myreader.webapi.crawler.read.HongChenReadCrawler \ No newline at end of file diff --git a/app/version_code.properties b/app/version_code.properties index fa1d8ee..2e56c3c 100644 --- a/app/version_code.properties +++ b/app/version_code.properties @@ -1,2 +1,2 @@ -#Sun Dec 06 20:42:20 CST 2020 -VERSION_CODE=176 +#Sat Dec 12 18:48:03 CST 2020 +VERSION_CODE=177