pull/5/head
fengyuecanzhu 4 years ago
parent 1e906116c2
commit f5a5d76b1e
  1. 2
      app/build.gradle
  2. 71
      app/src/main/java/xyz/fycz/myreader/entity/bookstore/FindBook.java
  3. 2
      app/src/main/java/xyz/fycz/myreader/entity/sourceedit/EditEntityUtil.kt
  4. 32
      app/src/main/java/xyz/fycz/myreader/greendao/entity/Book.java
  5. 1
      app/src/main/java/xyz/fycz/myreader/model/third2/content/BookInfo.java
  6. 9
      app/src/main/java/xyz/fycz/myreader/model/third2/content/BookList.java
  7. 20
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  8. 158
      app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java
  9. 19
      app/src/main/java/xyz/fycz/myreader/ui/activity/SourceEditActivity.java
  10. 10
      app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
  11. 1
      app/src/main/java/xyz/fycz/myreader/webapi/BookApi.java
  12. 2
      app/src/main/java/xyz/fycz/myreader/webapi/ThirdSourceApi.java
  13. 1
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/BiQuGeReadCrawler.java
  14. 1
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/FYReadCrawler.java
  15. 1
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/TianLaiReadCrawler.java
  16. 2
      app/src/main/res/layout/actiity_bookstore.xml
  17. 24
      app/src/main/res/layout/listview_book_type_item.xml

@ -208,7 +208,7 @@ dependencies {
}
greendao {
schemaVersion 27
schemaVersion 28
daoPackage 'xyz.fycz.myreader.greendao.gen'
// targetGenDir 'src/main/java'
}

@ -0,0 +1,71 @@
package xyz.fycz.myreader.entity.bookstore;
/**
* @author fengyue
* @date 2021/5/15 15:46
*/
public class FindBook {
private String name;
private String author;
private String imgUrl;
private String source;
private String center;
private String bottomLeft;
private String bottomRight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getCenter() {
return center;
}
public void setCenter(String center) {
this.center = center;
}
public String getBottomLeft() {
return bottomLeft;
}
public void setBottomLeft(String bottomLeft) {
this.bottomLeft = bottomLeft;
}
public String getBottomRight() {
return bottomRight;
}
public void setBottomRight(String bottomRight) {
this.bottomRight = bottomRight;
}
}

@ -17,7 +17,7 @@ object EditEntityUtil {
add(EditEntity("sourceGroup", source?.sourceGroup, R.string.source_group, "不同分组以;/,隔开"))
add(EditEntity("sourceCharset", source?.sourceCharset, R.string.source_charset, "默认UTF-8"))
add(EditEntity("sourceHeaders", source?.sourceHeaders, R.string.source_headers, "json格式"))
add(EditEntity("loginUrl", source?.loginUrl, R.string.login_url))
add(EditEntity("loginUrl", source?.loginUrl, R.string.login_url, ""))
add(EditEntity("sourceComment", source?.sourceComment, R.string.comment, "这是您留给使用者的说明"))
}
return sourceEntities

@ -22,11 +22,6 @@ import java.util.Objects;
import static xyz.fycz.myreader.common.APPCONST.MAP_STRING;
/**
*
* Created by fengyue on 2020/08/23.
*/
@Entity
public class Book implements Serializable {
@Transient
@ -47,7 +42,6 @@ public class Book implements Serializable {
private String status;
private String newestChapterId;//最新章节id
private String newestChapterTitle;//最新章节标题
private String newestChapterUrl;//最新章节url
private String historyChapterId;//上次关闭时的章节ID
private int histtoryChapterNum;//上次关闭时的章节数
@ -82,13 +76,17 @@ public class Book implements Serializable {
@Transient
private Map<String, String> variableMap;
@Generated(hash = 1284526947)
@Generated(hash = 1839243756)
public Book() {
}
@Generated(hash = 1910282685)
public Book(String id, String name, String chapterUrl, String infoUrl, String imgUrl, String desc,
String author, String type, String updateDate, String wordCount, String status,
String newestChapterId, String newestChapterTitle, String newestChapterUrl, String historyChapterId,
int histtoryChapterNum, int sortCode, int noReadNum, int chapterTotalNum, int lastReadPosition,
String source, boolean isCloseUpdate, boolean isDownLoadAll, String groupId, int groupSort,
String tag, Boolean replaceEnable, long lastReadTime, String variable) {
String newestChapterId, String newestChapterTitle, String historyChapterId, int histtoryChapterNum,
int sortCode, int noReadNum, int chapterTotalNum, int lastReadPosition, String source,
boolean isCloseUpdate, boolean isDownLoadAll, String groupId, int groupSort, String tag,
Boolean replaceEnable, long lastReadTime, String variable) {
this.id = id;
this.name = name;
this.chapterUrl = chapterUrl;
@ -102,7 +100,6 @@ public class Book implements Serializable {
this.status = status;
this.newestChapterId = newestChapterId;
this.newestChapterTitle = newestChapterTitle;
this.newestChapterUrl = newestChapterUrl;
this.historyChapterId = historyChapterId;
this.histtoryChapterNum = histtoryChapterNum;
this.sortCode = sortCode;
@ -120,11 +117,6 @@ public class Book implements Serializable {
this.variable = variable;
}
@Generated(hash = 1839243756)
public Book() {
}
@Override
public Object clone() {
try {
@ -196,12 +188,6 @@ public class Book implements Serializable {
public void setNewestChapterTitle(String newestChapterTitle) {
this.newestChapterTitle = newestChapterTitle;
}
public String getNewestChapterUrl() {
return this.newestChapterUrl;
}
public void setNewestChapterUrl(String newestChapterUrl) {
this.newestChapterUrl = newestChapterUrl;
}
public String getHistoryChapterId() {
return this.historyChapterId;
}

@ -27,6 +27,7 @@ public class BookInfo {
public Observable<Book> analyzeBookInfo(String s, final Book book) {
return Observable.create(e -> {
String baseUrl = book.getInfoUrl();
book.setInfoUrl(baseUrl);
InfoRule infoRule = source.getInfoRule();
if (TextUtils.isEmpty(s)) {
e.onError(new Throwable("书籍信息获取失败" + baseUrl));

@ -171,6 +171,7 @@ public class BookList {
item.setTag(tag);
item.setSource(bookSource.getSourceUrl());
item.setChapterUrl(baseUrl);
item.setInfoUrl(baseUrl);
Log.d(tag, ">书籍网址:" + baseUrl);
Log.d(tag, "┌获取书名");
String bookName = StringUtils.formatHtml(analyzer.getString(infoRule.getName()));
@ -185,13 +186,17 @@ public class BookList {
Log.d(tag, "└" + item.getType());
Log.d(tag, "┌获取最新章节");
item.setNewestChapterTitle(analyzer.getString(infoRule.getLastChapter()));
Log.d(tag, "└" + item.getNewestChapterId());
Log.d(tag, "└" + item.getNewestChapterTitle());
Log.d(tag, "┌获取简介");
item.setDesc(analyzer.getString(infoRule.getDesc()));
Log.d(tag, "└" + item.getDesc());
Log.d(tag, "┌获取封面");
item.setImgUrl(analyzer.getString(infoRule.getImgUrl(), true));
Log.d(tag, "└" + item.getImgUrl());
Log.d(tag, "┌获取目录网址");
String bookCatalogUrl = analyzer.getString(infoRule.getTocUrl(), true);
if (!isEmpty(bookCatalogUrl)) item.setChapterUrl(bookCatalogUrl);;
Log.d(tag, "└" + item.getChapterUrl());
return item;
}
return null;
@ -216,7 +221,7 @@ public class BookList {
if (printLog) Log.d(tag,"└" + item.getType());
if (printLog) Log.d(tag, "┌获取最新章节");
item.setNewestChapterTitle(String.valueOf(nativeObject.get(ruleLastChapter)));
if (printLog) Log.d(tag, "└" + item.getNewestChapterId());
if (printLog) Log.d(tag, "└" + item.getNewestChapterTitle());
if (printLog) Log.d(tag, "┌获取简介");
item.setDesc(String.valueOf(nativeObject.get(ruleIntroduce)));
if (printLog) Log.d(tag, "└" + item.getDesc());

@ -210,7 +210,7 @@ public class BookDetailedActivity extends BaseActivity {
binding.ic.bookDetailRvCatalog.setLayoutManager(new LinearLayoutManager(this));
binding.ic.bookDetailRvCatalog.setAdapter(mCatalogAdapter);
if (!thirdSource || isCollected) initChapters(false);
if (!thirdSource) initChapters(false);
mCatalogAdapter.setOnItemClickListener((view, pos) -> {
mBook.setHisttoryChapterNum(mChapters.size() - pos - 1);
@ -410,7 +410,7 @@ public class BookDetailedActivity extends BaseActivity {
BookSource source = BookSourceManager.getBookSourceByStr(mBook.getSource());
binding.ih.bookDetailSource.setText(String.format("书源:%s", source.getSourceName()));
ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source);
if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) || (thirdSource && !isCollected)) {
if ((rc instanceof BookInfoCrawler && StringHelper.isEmpty(mBook.getImgUrl())) || thirdSource) {
binding.pbLoading.setVisibility(View.VISIBLE);
BookInfoCrawler bic = (BookInfoCrawler) rc;
BookApi.getBookInfo(mBook, bic).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Book>() {
@ -418,17 +418,21 @@ public class BookDetailedActivity extends BaseActivity {
public void onNext(@NotNull Book book) {
if (!App.isDestroy(BookDetailedActivity.this)) {
mHandler.sendMessage(mHandler.obtainMessage(4));
if (thirdSource) {
initChapters(false);
}
}
if (thirdSource) {
initChapters(false);
}
}
@Override
public void onError(Throwable e) {
ToastUtils.showError("书籍详情加载失败!");
if (thirdSource) {
initChapters(false);
if (!App.isDestroy(BookDetailedActivity.this)) {
ToastUtils.showError("书籍详情加载失败!");
if (thirdSource) {
initChapters(false);
}
binding.pbLoading.setVisibility(View.GONE);
}
if (App.isDebug()) e.printStackTrace();
}

@ -10,35 +10,48 @@ import androidx.appcompat.widget.Toolbar;
import com.google.android.material.tabs.TabLayout;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.observer.MyObserver;
import xyz.fycz.myreader.databinding.ActivitySourceDebugBinding;
import xyz.fycz.myreader.entity.SearchBookBean;
import xyz.fycz.myreader.entity.StrResponse;
import xyz.fycz.myreader.entity.sourcedebug.DebugBook;
import xyz.fycz.myreader.entity.sourcedebug.DebugChapter;
import xyz.fycz.myreader.entity.sourcedebug.DebugEntity;
import xyz.fycz.myreader.entity.sourcedebug.ListResult;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConMVMap;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.webapi.BookApi;
import xyz.fycz.myreader.webapi.ThirdSourceApi;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.source.ThirdCrawler;
import xyz.fycz.myreader.widget.codeview.Language;
import static xyz.fycz.myreader.util.utils.OkHttpUtils.getCookies;
/**
* @author fengyue
* @date 2021/2/12 18:55
@ -149,52 +162,31 @@ public class SourceDebugActivity extends BaseActivity {
private void initDebugEntity() {
loadingDialog.show();
Observable.create((ObservableOnSubscribe<Boolean>) emitter -> {
try {
Observable<Boolean> observable;
if (rc instanceof ThirdCrawler) {
observable = debugThirdSource();
} else {
observable = Observable.create((ObservableOnSubscribe<StrResponse>) emitter -> {
String url = debugEntity.getUrl();
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));
if (debugEntity.getDebugMode() == DebugEntity.SEARCH && rc.isPost()) {
String[] urlInfo = url.split(",");
url = NetworkUtils.getAbsoluteURL(rc.getNameSpace(), urlInfo[0]);
String body = urlInfo[1];
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody requestBody = RequestBody.create(mediaType, body);
debugEntity.setHtml(OkHttpUtils.getHtml(url, requestBody, rc.getCharset(), rc.getHeaders()));
emitter.onNext(OkHttpUtils.getStrResponse(url, requestBody, rc.getCharset(), headers));
} else {
debugEntity.setHtml(OkHttpUtils.getHtml(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), url), rc.getCharset(), rc.getHeaders()));
emitter.onNext((OkHttpUtils.getStrResponse(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), url), rc.getCharset(), headers)));
}
ListResult listResult = new ListResult();
switch (debugEntity.getDebugMode()) {
case DebugEntity.SEARCH:
default:
List<DebugBook> debugBooks = book2DebugBook(rc.getBooksFromSearchHtml(debugEntity.getHtml()).values());
listResult.set信息(String.format("解析完毕,共%s本书籍", debugBooks.size()));
listResult.set结果(debugBooks);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
break;
case DebugEntity.INFO:
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(book2DebugBook(((BookInfoCrawler) rc).getBookInfo(debugEntity.getHtml(), new Book()))));
break;
case DebugEntity.TOC:
List<DebugChapter> debugChapters = chapter2DebugChapter(rc.getChaptersFromHtml(debugEntity.getHtml()));
listResult.set信息(String.format("解析完毕,共%s个章节", debugChapters.size()));
listResult.set结果(debugChapters);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
break;
case DebugEntity.CONTENT:
debugEntity.setParseResult(rc.getContentFormHtml(debugEntity.getHtml()));
break;
}
emitter.onNext(true);
} catch (Exception e) {
e.printStackTrace();
emitter.onError(e);
}
emitter.onComplete();
}).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Boolean>() {
emitter.onComplete();
}).flatMap(response -> OkHttpUtils.setCookie(response, rc.getNameSpace()))
.flatMap((Function<StrResponse, ObservableSource<Boolean>>) this::debugSource);
}
observable.compose(RxUtils::toSimpleSingle).subscribe(new MyObserver<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
@ -214,10 +206,102 @@ public class SourceDebugActivity extends BaseActivity {
binding.rvSourceCode.setCode(debugEntity.getHtml()).apply();
loadingDialog.dismiss();
}
});
}
private Observable<Boolean> debugSource(StrResponse response) {
debugEntity.setHtml(response.body());
ListResult listResult = new ListResult();
switch (debugEntity.getDebugMode()) {
case DebugEntity.SEARCH:
default:
return rc.getBooksFromStrResponse(response)
.flatMap((Function<ConMVMap<SearchBookBean, Book>, ObservableSource<Boolean>>) books -> Observable.create(emitter -> {
List<DebugBook> debugBooks = book2DebugBook(books.values());
listResult.set信息(String.format("解析完毕,共%s本书籍", debugBooks.size()));
listResult.set结果(debugBooks);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.INFO:
return ((BookInfoCrawler) rc).getBookInfo(response, new Book())
.flatMap((Function<Book, ObservableSource<Boolean>>) book -> Observable.create(emitter -> {
debugEntity.setParseResult(GsonExtensionsKt.getGSON().toJson(book2DebugBook(book)));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.TOC:
return rc.getChaptersFromStrResponse(response)
.flatMap((Function<List<Chapter>, ObservableSource<Boolean>>) chapters -> Observable.create(emitter -> {
List<DebugChapter> debugChapters = chapter2DebugChapter(chapters);
listResult.set信息(String.format("解析完毕,共%s个章节", debugChapters.size()));
listResult.set结果(debugChapters);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.CONTENT:
return rc.getContentFormStrResponse(response)
.flatMap((Function<String, ObservableSource<Boolean>>) content -> Observable.create(emitter -> {
debugEntity.setParseResult(content);
emitter.onNext(true);
emitter.onComplete();
}));
}
}
private Observable<Boolean> debugThirdSource() {
debugEntity.setHtml("第三方书源不支持查看源码");
ListResult listResult = new ListResult();
Book book = new Book();
book.setChapterUrl(debugEntity.getUrl());
switch (debugEntity.getDebugMode()) {
case DebugEntity.SEARCH:
default:
return BookApi.search(debugEntity.getKey(), rc)
.flatMap((Function<ConMVMap<SearchBookBean, Book>, ObservableSource<Boolean>>) books -> Observable.create(emitter -> {
List<DebugBook> debugBooks = book2DebugBook(books.values());
listResult.set信息(String.format("解析完毕,共%s本书籍", debugBooks.size()));
listResult.set结果(debugBooks);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.INFO:
return BookApi.getBookInfo(book, (BookInfoCrawler) rc)
.flatMap((Function<Book, ObservableSource<Boolean>>) book1 -> Observable.create(emitter -> {
debugEntity.setParseResult(GsonExtensionsKt.getGSON().toJson(book2DebugBook(book1)));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.TOC:
return BookApi.getBookChapters(book, rc)
.flatMap((Function<List<Chapter>, ObservableSource<Boolean>>) chapters -> Observable.create(emitter -> {
List<DebugChapter> debugChapters = chapter2DebugChapter(chapters);
listResult.set信息(String.format("解析完毕,共%s个章节", debugChapters.size()));
listResult.set结果(debugChapters);
debugEntity.setParseResult(GsonExtensionsKt.getGSON()
.toJson(listResult));
emitter.onNext(true);
emitter.onComplete();
}));
case DebugEntity.CONTENT:
Chapter chapter = new Chapter();
book.setChapterUrl(rc.getNameSpace());
chapter.setUrl(debugEntity.getUrl());
return BookApi.getChapterContent(chapter, book, rc)
.flatMap((Function<String, ObservableSource<Boolean>>) content -> Observable.create(emitter -> {
debugEntity.setParseResult(content);
emitter.onNext(true);
emitter.onComplete();
}));
}
}
private List<DebugBook> book2DebugBook(List<Book> books) {
List<DebugBook> debugBooks = new ArrayList<>();
for (Book book : books) {

@ -141,17 +141,6 @@ public class SourceEditActivity extends BaseActivity {
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
binding.sSourceType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
invalidateOptionsMenu();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
@ -162,13 +151,6 @@ public class SourceEditActivity extends BaseActivity {
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem debug = menu.findItem(R.id.action_debug);
debug.setVisible(!APPCONST.THIRD_SOURCE.equals(getSource().getSourceType()));
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_save) {
@ -216,6 +198,7 @@ public class SourceEditActivity extends BaseActivity {
MyAlertDialog.createInputDia(this, String.valueOf(title), hint,
"", true, 500, text -> {
if (debugMode == DebugEntity.SEARCH) {
debugEntity.setKey(text);
try {
MatcherCrawler sc = new MatcherCrawler(source);
if (!sc.getSearchCharset().toLowerCase().equals("utf-8")) {

@ -5,6 +5,8 @@ import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -77,5 +79,11 @@ public interface JsExtensions {
.execute();
}
/**
* 时间格式化
*/
default String timeFormat(long time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
return sdf.format(new Date(time));
}
}

@ -123,7 +123,6 @@ public class BookApi {
/**
* 获取章节正文
*/
public static Observable<String> getChapterContent(Chapter chapter, Book book, final ReadCrawler rc) {
if (rc instanceof ThirdCrawler) {
return ThirdSourceApi.getChapterContentByTC(chapter, book, (ThirdCrawler) rc);

@ -40,7 +40,7 @@ public class ThirdSourceApi {
* @param rc
* @return
*/
public static Observable<ConMVMap<SearchBookBean, Book>> searchByTC(String key, final ThirdCrawler rc) {
protected static Observable<ConMVMap<SearchBookBean, Book>> searchByTC(String key, final ThirdCrawler rc) {
try {
Map<String, String> headers = rc.getHeaders();
headers.putAll(getCookies(rc.getNameSpace()));

@ -231,7 +231,6 @@ public class BiQuGeReadCrawler extends BaseReadCrawler implements BookInfoCrawle
Element p3 = ps.get(3);
a = p3.getElementsByTag("a").get(0);
book.setNewestChapterTitle(a.attr("title"));
book.setNewestChapterUrl(book.getChapterUrl() + a.attr("href"));
//类型
String type = doc.select("meta[property=og:novel:category]").attr("content");

@ -108,7 +108,6 @@ public class FYReadCrawler extends BaseReadCrawler {
book.setAuthor(div.getElementsByTag("a").get(2).text());
book.setType(div.getElementsByTag("a").get(3).text());
book.setNewestChapterTitle(div.getElementsByTag("a").get(4).text());
book.setNewestChapterUrl(div.getElementsByTag("a").get(4).attr("href"));
Element img = div.getElementsByTag("img").get(0);
book.setImgUrl(img.attr("data-original"));
Element chapterUrl = div.getElementsByTag("a").get(1);

@ -143,7 +143,6 @@ public class TianLaiReadCrawler extends BaseReadCrawler {
book.setUpdateDate(infoStr.replace("更新时间:", "").replace(" ", ""));
} else {
Element newChapter = element1.child(1);
book.setNewestChapterUrl(newChapter.attr("href"));
book.setNewestChapterTitle(newChapter.text());
}
}

@ -24,7 +24,7 @@
android:id="@+id/rv_type_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="10">
android:layout_weight="12">
</androidx.recyclerview.widget.RecyclerView>
<RelativeLayout

@ -2,21 +2,21 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorBackground"
android:gravity="center"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="18dp"
android:paddingBottom="18dp"
android:gravity="center"
android:background="@color/colorBackground">
android:paddingRight="8dp"
android:paddingBottom="18dp">
<TextView
android:id="@+id/tv_type_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/textSecondary"
android:text="玄幻小说"
android:textSize="14sp">
<TextView
android:id="@+id/tv_type_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLength="4"
android:textColor="@color/textSecondary"
android:textSize="13sp">
</TextView>
</TextView>
</LinearLayout>
Loading…
Cancel
Save