|
|
|
|
@ -33,61 +33,32 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
|
|
import io.reactivex.functions.Function;
|
|
|
|
|
import io.reactivex.schedulers.Schedulers;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GxwztvBookModelImpl类继承自MBaseModelImpl并实现了IGxwztvBookModel接口,主要用于与特定网站(由TAG标识为http://www.gxwztv.com)
|
|
|
|
|
* 进行交互,实现诸如获取网站主页信息、搜索书籍、获取书籍详情、章节列表以及章节内容等功能,通过解析网页HTML结构提取相关数据,
|
|
|
|
|
* 并利用RxJava进行异步操作和数据流转处理,最终将处理好的数据以合适的形式返回给调用者,应用于阅读相关的业务场景中。
|
|
|
|
|
*/
|
|
|
|
|
public class GxwztvBookModelImpl extends MBaseModelImpl implements IGxwztvBookModel {
|
|
|
|
|
|
|
|
|
|
// 定义一个静态常量TAG,用于标识该模型所对应的网站地址,此处明确为http://www.gxwztv.com,
|
|
|
|
|
// 便于在整个程序体系里知晓此模型相关的网络操作、数据解析等逻辑是针对该站点而设计的。
|
|
|
|
|
public static final String TAG = "http://www.gxwztv.com";
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取GxwztvBookModelImpl类的单例实例。
|
|
|
|
|
* 通过采用单例模式,确保在整个程序运行期间只有一个该类的实例存在,这样可以更有序地对与该网站交互、解析相关数据等功能进行统一管理与调用,
|
|
|
|
|
* 避免因创建多个实例可能导致的资源管理混乱、逻辑不一致等问题。
|
|
|
|
|
*
|
|
|
|
|
* @return 返回GxwztvBookModelImpl类的唯一实例对象。
|
|
|
|
|
*/
|
|
|
|
|
public static GxwztvBookModelImpl getInstance() {
|
|
|
|
|
return new GxwztvBookModelImpl();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取主页信息
|
|
|
|
|
* 此方法通过网络请求获取网站主页数据,先尝试将获取到的数据缓存起来(如果数据有效且缓存对象不为空),
|
|
|
|
|
* 然后调用解析主页数据的方法对获取到的数据进行解析处理,最终返回一个包含解析后主页信息的Observable对象,
|
|
|
|
|
* 方便后续在RxJava的响应式编程模式下进行订阅和处理。
|
|
|
|
|
*
|
|
|
|
|
* @param aCache 用于缓存数据的ACache对象,可将获取到的主页数据缓存起来以便后续快速访问,减少重复网络请求。
|
|
|
|
|
* @return 返回一个Observable对象,其发射类型为LibraryBean,包含了解析后的网站主页相关信息,例如最新书籍、各类书籍分类列表等。
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<LibraryBean> getLibraryData(final ACache aCache) {
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).getLibraryData("")
|
|
|
|
|
// 使用flatMap操作符,将网络请求获取到的字符串数据进行进一步处理,先尝试缓存数据,再进行解析操作
|
|
|
|
|
.flatMap(new Function<String, ObservableSource<LibraryBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<LibraryBean> apply(String s) throws Exception {
|
|
|
|
|
// 如果获取到的数据不为空且长度大于0,并且缓存对象不为空,则将数据存入缓存,缓存的键由LibraryPresenterImpl.LIBRARY_CACHE_KEY指定
|
|
|
|
|
if (s!= null && s.length() > 0 && aCache!= null) {
|
|
|
|
|
aCache.put(LibraryPresenterImpl.LIBRARY_CACHE_KEY, s);
|
|
|
|
|
}
|
|
|
|
|
// 调用解析主页数据的方法,将获取到的数据传入进行解析,并返回解析后的Observable对象
|
|
|
|
|
return analyLibraryData(s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).getLibraryData("").flatMap(new Function<String, ObservableSource<LibraryBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<LibraryBean> apply(String s) throws Exception {
|
|
|
|
|
if (s != null && s.length() > 0 && aCache != null) {
|
|
|
|
|
aCache.put(LibraryPresenterImpl.LIBRARY_CACHE_KEY, s);
|
|
|
|
|
}
|
|
|
|
|
return analyLibraryData(s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 解析主页数据
|
|
|
|
|
* 此方法在Observable的订阅逻辑中被调用,用于解析从网站主页获取到的HTML格式数据,从中提取出如最新书籍、不同分类书籍等信息,
|
|
|
|
|
* 并将这些信息封装到LibraryBean对象中,最后通过ObservableEmitter发射出去,供订阅者接收处理。
|
|
|
|
|
*
|
|
|
|
|
* @param data 包含网站主页内容的原始字符串数据,通常为HTML格式,是从网络请求获取到的主页信息。
|
|
|
|
|
* @return 返回一个Observable对象,其发射类型为LibraryBean,包含了解析后的主页相关信息。
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<LibraryBean> analyLibraryData(final String data) {
|
|
|
|
|
@ -95,35 +66,24 @@ public class GxwztvBookModelImpl extends MBaseModelImpl implements IGxwztvBookMo
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(ObservableEmitter<LibraryBean> e) throws Exception {
|
|
|
|
|
LibraryBean result = new LibraryBean();
|
|
|
|
|
// 使用Jsoup库将传入的HTML格式字符串数据解析为Document对象,以便后续按照DOM结构查找和提取元素及内容
|
|
|
|
|
Document doc = Jsoup.parse(data);
|
|
|
|
|
// 通过元素的类名获取名为"container"的元素,这里假设主页的主要内容都在这个元素内部,是后续提取各种信息的基础元素
|
|
|
|
|
Element contentE = doc.getElementsByClass("container").get(0);
|
|
|
|
|
|
|
|
|
|
// 解析最新书籍信息
|
|
|
|
|
// 获取所有类名为"list-group-item text-nowrap modal-open"的元素,这些元素被认为包含了最新书籍的相关信息
|
|
|
|
|
//解析最新书籍
|
|
|
|
|
Elements newBookEs = contentE.getElementsByClass("list-group-item text-nowrap modal-open");
|
|
|
|
|
List<LibraryNewBookBean> libraryNewBooks = new ArrayList<LibraryNewBookBean>();
|
|
|
|
|
for (int i = 0; i < newBookEs.size(); i++) {
|
|
|
|
|
// 从每个包含最新书籍信息的元素中获取<a>标签元素,通常<a>标签包含了书籍的链接、书名等关键信息
|
|
|
|
|
Element itemE = newBookEs.get(i).getElementsByTag("a").get(0);
|
|
|
|
|
// 创建一个LibraryNewBookBean对象,将书名、书籍链接等信息封装进去,其中链接是在TAG基础上拼接获取到的相对链接
|
|
|
|
|
LibraryNewBookBean item = new LibraryNewBookBean(itemE.text(), TAG + itemE.attr("href"), TAG, "gxwztv.com");
|
|
|
|
|
libraryNewBooks.add(item);
|
|
|
|
|
}
|
|
|
|
|
result.setLibraryNewBooks(libraryNewBooks);
|
|
|
|
|
|
|
|
|
|
// 解析不同分类书籍信息,先初始化一个空的列表用于存放不同分类的书籍列表信息
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
List<LibraryKindBookListBean> kindBooks = new ArrayList<LibraryKindBookListBean>();
|
|
|
|
|
|
|
|
|
|
// 解析男频女频分类书籍信息
|
|
|
|
|
// 获取所有类名为"col-xs-12"的元素,这里假设这些元素包含了男频女频相关的分类信息
|
|
|
|
|
//解析男频女频
|
|
|
|
|
Elements hotEs = contentE.getElementsByClass("col-xs-12");
|
|
|
|
|
for (int i = 1; i < hotEs.size(); i++) {
|
|
|
|
|
LibraryKindBookListBean kindItem = new LibraryKindBookListBean();
|
|
|
|
|
// 获取分类名称,即通过类名为"panel-title"的元素获取其文本内容作为分类名
|
|
|
|
|
kindItem.setKindName(hotEs.get(i).getElementsByClass("panel-title").get(0).text());
|
|
|
|
|
// 获取该分类下的书籍元素列表,通过先获取类名为"panel-body"的元素,再获取其内部的<li>标签元素来定位书籍信息所在元素
|
|
|
|
|
Elements bookEs = hotEs.get(i).getElementsByClass("panel-body").get(0).getElementsByTag("li");
|
|
|
|
|
|
|
|
|
|
List<SearchBookBean> books = new ArrayList<SearchBookBean>();
|
|
|
|
|
@ -131,59 +91,47 @@ public class GxwztvBookModelImpl extends MBaseModelImpl implements IGxwztvBookMo
|
|
|
|
|
SearchBookBean searchBookBean = new SearchBookBean();
|
|
|
|
|
searchBookBean.setOrigin("gxwztv.com");
|
|
|
|
|
searchBookBean.setTag(TAG);
|
|
|
|
|
// 获取书籍名称,通过获取<span>标签的文本内容作为书名
|
|
|
|
|
searchBookBean.setName(bookEs.get(j).getElementsByTag("span").get(0).text());
|
|
|
|
|
// 获取书籍详情链接,同样是在TAG基础上拼接相对链接
|
|
|
|
|
searchBookBean.setNoteUrl(TAG + bookEs.get(j).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
// 获取书籍封面链接,通过获取<img>标签的src属性值作为封面链接
|
|
|
|
|
searchBookBean.setCoverUrl(bookEs.get(j).getElementsByTag("img").get(0).attr("src"));
|
|
|
|
|
books.add(searchBookBean);
|
|
|
|
|
}
|
|
|
|
|
kindItem.setBooks(books);
|
|
|
|
|
kindBooks.add(kindItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解析部分分类推荐书籍信息
|
|
|
|
|
// 获取所有类名为"panel panel-info index-category-qk"的元素,这些元素包含了部分分类推荐的相关信息
|
|
|
|
|
//解析部分分类推荐
|
|
|
|
|
Elements kindEs = contentE.getElementsByClass("panel panel-info index-category-qk");
|
|
|
|
|
for (int i = 0; i < kindEs.size(); i++) {
|
|
|
|
|
LibraryKindBookListBean kindItem = new LibraryKindBookListBean();
|
|
|
|
|
kindItem.setKindName(kindEs.get(i).getElementsByClass("panel-title").get(0).text());
|
|
|
|
|
// 获取分类链接,同样是在TAG基础上拼接相对链接
|
|
|
|
|
kindItem.setKindUrl(TAG + kindEs.get(i).getElementsByClass("listMore").get(0).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
|
|
|
|
|
List<SearchBookBean> books = new ArrayList<SearchBookBean>();
|
|
|
|
|
// 获取第一个推荐书籍的元素,这里通过<dl>标签来定位
|
|
|
|
|
Element firstBookE = kindEs.get(i).getElementsByTag("dl").get(0);
|
|
|
|
|
SearchBookBean firstBook = new SearchBookBean();
|
|
|
|
|
firstBook.setTag(TAG);
|
|
|
|
|
firstBook.setOrigin("gxwztv.com");
|
|
|
|
|
// 获取书籍名称,通过获取<a>标签的文本内容作为书名(这里取第二个<a>标签的文本,可能是根据网页结构来确定的具体书名所在位置)
|
|
|
|
|
firstBook.setName(firstBookE.getElementsByTag("a").get(1).text());
|
|
|
|
|
// 获取书籍详情链接,在TAG基础上拼接相对链接
|
|
|
|
|
firstBook.setNoteUrl(TAG + firstBookE.getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
// 获取书籍封面链接,通过获取<a>标签下的<img>标签的src属性值作为封面链接
|
|
|
|
|
firstBook.setCoverUrl(firstBookE.getElementsByTag("a").get(0).getElementsByTag("img").get(0).attr("src"));
|
|
|
|
|
firstBook.setKind(kindItem.getKindName());
|
|
|
|
|
books.add(firstBook);
|
|
|
|
|
|
|
|
|
|
// 获取其他推荐书籍的元素列表,通过类名为"book_textList"的元素下的<li>标签来定位
|
|
|
|
|
Elements otherBookEs = kindEs.get(i).getElementsByClass("book_textList").get(0).getElementsByTag("li");
|
|
|
|
|
for (int j = 0; j < otherBookEs.size(); j++) {
|
|
|
|
|
SearchBookBean item = new SearchBookBean();
|
|
|
|
|
item.setTag(TAG);
|
|
|
|
|
item.setOrigin("gxwztv.com");
|
|
|
|
|
item.setKind(kindItem.getKindName());
|
|
|
|
|
item.setNoteUrl(TAG + otherBookEs.get(j).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
item.setNoteUrl(TAG+otherBookEs.get(j).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
item.setName(otherBookEs.get(j).getElementsByTag("a").get(0).text());
|
|
|
|
|
books.add(item);
|
|
|
|
|
}
|
|
|
|
|
kindItem.setBooks(books);
|
|
|
|
|
kindBooks.add(kindItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////
|
|
|
|
|
result.setKindBooks(kindBooks);
|
|
|
|
|
// 通过ObservableEmitter发射解析好的LibraryBean对象,包含了主页上的各种书籍相关信息
|
|
|
|
|
e.onNext(result);
|
|
|
|
|
e.onComplete();
|
|
|
|
|
}
|
|
|
|
|
@ -191,58 +139,33 @@ public class GxwztvBookModelImpl extends MBaseModelImpl implements IGxwztvBookMo
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 搜索书籍功能
|
|
|
|
|
* 根据传入的搜索内容和页码,向网站发起搜索书籍的网络请求,然后调用解析搜索书籍结果的方法对返回的数据进行解析,
|
|
|
|
|
* 最终返回一个包含搜索结果(以SearchBookBean列表形式表示)的Observable对象,供订阅者接收处理搜索到的书籍信息。
|
|
|
|
|
*
|
|
|
|
|
* @param content 用于搜索书籍的关键字内容,指定要搜索的书籍相关的关键词,比如书名、作者等。
|
|
|
|
|
* @param page 搜索结果的页码,用于获取指定页码的搜索结果数据,实现分页查询功能。
|
|
|
|
|
* @return 返回一个Observable对象,其发射类型为List<SearchBookBean>,包含了搜索到的符合条件的书籍信息列表。
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<List<SearchBookBean>> searchBook(String content, int page) {
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).searchBook(content, page)
|
|
|
|
|
.flatMap(new Function<String, ObservableSource<List<SearchBookBean>>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<List<SearchBookBean>> apply(String s) throws Exception {
|
|
|
|
|
return analySearchBook(s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).searchBook(content, page).flatMap(new Function<String, ObservableSource<List<SearchBookBean>>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<List<SearchBookBean>> apply(String s) throws Exception {
|
|
|
|
|
return analySearchBook(s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 解析搜索书籍结果
|
|
|
|
|
* 此方法在搜索书籍的网络请求返回数据后被调用,用于解析获取到的HTML格式的搜索结果数据,从中提取出每本搜索到的书籍的相关信息,
|
|
|
|
|
* 如书名、作者、链接等,并将这些信息封装到SearchBookBean对象中,最后组成列表通过ObservableEmitter发射出去,供订阅者接收处理。
|
|
|
|
|
*
|
|
|
|
|
* @param s 包含搜索书籍结果内容的原始字符串数据,通常为HTML格式,是从网络请求获取到的搜索结果信息。
|
|
|
|
|
* @return 返回一个Observable对象,其发射类型为List<SearchBookBean>,包含了解析后的搜索到的书籍信息列表。
|
|
|
|
|
*/
|
|
|
|
|
public Observable<List<SearchBookBean>> analySearchBook(final String s) {
|
|
|
|
|
return Observable.create(new ObservableOnSubscribe<List<SearchBookBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(ObservableEmitter<List<SearchBookBean>> e) throws Exception {
|
|
|
|
|
try {
|
|
|
|
|
Document doc = Jsoup.parse(s);
|
|
|
|
|
// 获取id为"novel-list"的元素下类名为"list-group-item clearfix"的元素列表,这里假设这些元素包含了搜索到的每本书籍的相关信息
|
|
|
|
|
Elements booksE = doc.getElementById("novel-list").getElementsByClass("list-group-item clearfix");
|
|
|
|
|
if (null!= booksE && booksE.size() >= 2) {
|
|
|
|
|
if (null != booksE && booksE.size() >= 2) {
|
|
|
|
|
List<SearchBookBean> books = new ArrayList<SearchBookBean>();
|
|
|
|
|
for (int i = 1; i < booksE.size(); i++) {
|
|
|
|
|
SearchBookBean item = new SearchBookBean();
|
|
|
|
|
item.setTag(TAG);
|
|
|
|
|
// 获取书籍作者信息,通过类名为"col-xs-2"的元素获取其文本内容作为作者名
|
|
|
|
|
item.setAuthor(booksE.get(i).getElementsByClass("col-xs-2").get(0).text());
|
|
|
|
|
// 获取书籍分类信息,通过类名为"col-xs-1"的元素获取其文本内容作为分类名
|
|
|
|
|
item.setKind(booksE.get(i).getElementsByClass("col-xs-1").get(0).text());
|
|
|
|
|
// 获取书籍最后章节信息,通过类名为"col-xs-4"的元素下的<a>标签获取其文本内容作为最后章节名
|
|
|
|
|
item.setLastChapter(booksE.get(i).getElementsByClass("col-xs-4").get(0).getElementsByTag("a").get(0).text());
|
|
|
|
|
item.setOrigin("gxwztv.com");
|
|
|
|
|
// 获取书籍名称,通过类名为"col-xs-3"的元素下的<a>标签获取其文本内容作为书名
|
|
|
|
|
item.setName(booksE.get(i).getElementsByClass("col-xs-3").get(0).getElementsByTag("a").get(0).text());
|
|
|
|
|
// 获取书籍详情链接,在TAG基础上拼接相对链接
|
|
|
|
|
item.setNoteUrl(TAG + booksE.get(i).getElementsByClass("col-xs-3").get(0).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
item.setCoverUrl("noimage");
|
|
|
|
|
books.add(item);
|
|
|
|
|
@ -260,8 +183,171 @@ public class GxwztvBookModelImpl extends MBaseModelImpl implements IGxwztvBookMo
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<BookShelfBean> getBookInfo(final BookShelfBean bookShelfBean) {
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).getBookInfo(bookShelfBean.getNoteUrl().replace(TAG, "")).flatMap(new Function<String, ObservableSource<BookShelfBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<BookShelfBean> apply(String s) throws Exception {
|
|
|
|
|
return analyBookInfo(s, bookShelfBean);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Observable<BookShelfBean> analyBookInfo(final String s, final BookShelfBean bookShelfBean) {
|
|
|
|
|
return Observable.create(new ObservableOnSubscribe<BookShelfBean>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(ObservableEmitter<BookShelfBean> e) throws Exception {
|
|
|
|
|
bookShelfBean.setTag(TAG);
|
|
|
|
|
bookShelfBean.setBookInfoBean(analyBookinfo(s, bookShelfBean.getNoteUrl()));
|
|
|
|
|
e.onNext(bookShelfBean);
|
|
|
|
|
e.onComplete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private BookInfoBean analyBookinfo(String s, String novelUrl) {
|
|
|
|
|
BookInfoBean bookInfoBean = new BookInfoBean();
|
|
|
|
|
bookInfoBean.setNoteUrl(novelUrl); //id
|
|
|
|
|
bookInfoBean.setTag(TAG);
|
|
|
|
|
Document doc = Jsoup.parse(s);
|
|
|
|
|
Element resultE = doc.getElementsByClass("panel panel-warning").get(0);
|
|
|
|
|
bookInfoBean.setCoverUrl(resultE.getElementsByClass("panel-body").get(0).getElementsByClass("img-thumbnail").get(0).attr("src"));
|
|
|
|
|
bookInfoBean.setName(resultE.getElementsByClass("active").get(0).text());
|
|
|
|
|
bookInfoBean.setAuthor(resultE.getElementsByClass("col-xs-12 list-group-item no-border").get(0).getElementsByTag("small").get(0).text());
|
|
|
|
|
Element introduceE = resultE.getElementsByClass("panel panel-default mt20").get(0);
|
|
|
|
|
String introduce = "";
|
|
|
|
|
if (introduceE.getElementById("all") != null) {
|
|
|
|
|
introduce = introduceE.getElementById("all").text().replace("[收起]", "");
|
|
|
|
|
} else {
|
|
|
|
|
introduce = introduceE.getElementById("shot").text();
|
|
|
|
|
}
|
|
|
|
|
bookInfoBean.setIntroduce("\u3000\u3000" + introduce);
|
|
|
|
|
bookInfoBean.setChapterUrl(TAG + resultE.getElementsByClass("list-group-item tac").get(0).getElementsByTag("a").get(0).attr("href"));
|
|
|
|
|
bookInfoBean.setOrigin("gxwztv.com");
|
|
|
|
|
return bookInfoBean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
@Override
|
|
|
|
|
public void getChapterList(final BookShelfBean bookShelfBean, final OnGetChapterListListener getChapterListListener) {
|
|
|
|
|
getRetrofitObject(TAG).create(IGxwztvApi.class).getChapterList(bookShelfBean.getBookInfoBean().getChapterUrl().replace(TAG, "")).flatMap(new Function<String, ObservableSource<WebChapterBean<BookShelfBean>>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<WebChapterBean<BookShelfBean>> apply(String s) throws Exception {
|
|
|
|
|
return analyChapterList(s, bookShelfBean);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.subscribeOn(Schedulers.io())
|
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
|
.subscribe(new SimpleObserver<WebChapterBean<BookShelfBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onNext(WebChapterBean<BookShelfBean> value) {
|
|
|
|
|
if (getChapterListListener != null) {
|
|
|
|
|
getChapterListListener.success(value.getData());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onError(Throwable e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
if (getChapterListListener != null) {
|
|
|
|
|
getChapterListListener.error();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Observable<WebChapterBean<BookShelfBean>> analyChapterList(final String s, final BookShelfBean bookShelfBean) {
|
|
|
|
|
return Observable.create(new ObservableOnSubscribe<WebChapterBean<BookShelfBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(ObservableEmitter<WebChapterBean<BookShelfBean>> e) throws Exception {
|
|
|
|
|
bookShelfBean.setTag(TAG);
|
|
|
|
|
WebChapterBean<List<ChapterListBean>> temp = analyChapterlist(s, bookShelfBean.getNoteUrl());
|
|
|
|
|
bookShelfBean.getBookInfoBean().setChapterlist(temp.getData());
|
|
|
|
|
e.onNext(new WebChapterBean<BookShelfBean>(bookShelfBean, temp.getNext()));
|
|
|
|
|
e.onComplete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private WebChapterBean<List<ChapterListBean>> analyChapterlist(String s, String novelUrl) {
|
|
|
|
|
Document doc = Jsoup.parse(s);
|
|
|
|
|
Elements chapterlist = doc.getElementById("chapters-list").getElementsByTag("a");
|
|
|
|
|
List<ChapterListBean> chapterBeans = new ArrayList<ChapterListBean>();
|
|
|
|
|
for (int i = 0; i < chapterlist.size(); i++) {
|
|
|
|
|
ChapterListBean temp = new ChapterListBean();
|
|
|
|
|
temp.setDurChapterUrl(TAG + chapterlist.get(i).attr("href")); //id
|
|
|
|
|
temp.setDurChapterIndex(i);
|
|
|
|
|
temp.setDurChapterName(chapterlist.get(i).text());
|
|
|
|
|
temp.setNoteUrl(novelUrl);
|
|
|
|
|
temp.setTag(TAG);
|
|
|
|
|
|
|
|
|
|
chapterBeans.add(temp);
|
|
|
|
|
}
|
|
|
|
|
Boolean next = false;
|
|
|
|
|
return new WebChapterBean<List<ChapterListBean>>(chapterBeans, next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<BookContentBean> getBookContent(final String durChapterUrl, final int durChapterIndex) {
|
|
|
|
|
return getRetrofitObject(TAG).create(IGxwztvApi.class).getBookContent(durChapterUrl.replace(TAG, "")).flatMap(new Function<String, ObservableSource<BookContentBean>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<BookContentBean> apply(String s) throws Exception {
|
|
|
|
|
return analyBookContent(s, durChapterUrl, durChapterIndex);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Observable<BookContentBean> analyBookContent(final String s, final String durChapterUrl, final int durChapterIndex) {
|
|
|
|
|
return Observable.create(new ObservableOnSubscribe<BookContentBean>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void subscribe(ObservableEmitter<BookContentBean> e) throws Exception {
|
|
|
|
|
BookContentBean bookContentBean = new BookContentBean();
|
|
|
|
|
bookContentBean.setDurChapterIndex(durChapterIndex);
|
|
|
|
|
bookContentBean.setDurChapterUrl(durChapterUrl);
|
|
|
|
|
bookContentBean.setTag(TAG);
|
|
|
|
|
try {
|
|
|
|
|
Document doc = Jsoup.parse(s);
|
|
|
|
|
List<TextNode> contentEs = doc.getElementById("txtContent").textNodes();
|
|
|
|
|
StringBuilder content = new StringBuilder();
|
|
|
|
|
for (int i = 0; i < contentEs.size(); i++) {
|
|
|
|
|
String temp = contentEs.get(i).text().trim();
|
|
|
|
|
temp = temp.replaceAll(" ", "").replaceAll(" ", "");
|
|
|
|
|
if (temp.length() > 0) {
|
|
|
|
|
content.append("\u3000\u3000" + temp);
|
|
|
|
|
if (i < contentEs.size() - 1) {
|
|
|
|
|
content.append("\r\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bookContentBean.setDurCapterContent(content.toString());
|
|
|
|
|
bookContentBean.setRight(true);
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
ex.printStackTrace();
|
|
|
|
|
ErrorAnalyContentManager.getInstance().writeNewErrorUrl(durChapterUrl);
|
|
|
|
|
bookContentBean.setDurCapterContent(durChapterUrl.substring(0, durChapterUrl.indexOf('/', 8)) + "站点暂时不支持解析,请反馈给Monke QQ:1105075896,半小时内解决,超级效率的程序员");
|
|
|
|
|
bookContentBean.setRight(false);
|
|
|
|
|
}
|
|
|
|
|
e.onNext(bookContentBean);
|
|
|
|
|
e.onComplete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取书籍详情信息
|
|
|
|
|
* 根据传入的BookShelfBean
|
|
|
|
|
/**
|
|
|
|
|
* 获取分类书籍
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Observable<List<SearchBookBean>> getKindBook(String url, int page) {
|
|
|
|
|
url = url + page + ".htm";
|
|
|
|
|
return getRetrofitObject(GxwztvBookModelImpl.TAG).create(IGxwztvApi.class).getKindBooks(url.replace(GxwztvBookModelImpl.TAG, "")).flatMap(new Function<String, ObservableSource<List<SearchBookBean>>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public ObservableSource<List<SearchBookBean>> apply(String s) throws Exception {
|
|
|
|
|
return analySearchBook(s);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|