mirror of
https://github.com/201206030/novel.git
synced 2025-07-07 13:26:38 +00:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
05d9e22df9 | |||
ef36527ed6 | |||
6688d5b017 | |||
b242d6d89f | |||
5ec0f39b89 | |||
bc445548ce | |||
7c3fb654bb | |||
060429001c | |||
df60698082 | |||
979bcb47df | |||
495bd40644 | |||
52f6bd2519 | |||
0e4c181265 | |||
2a05353d95 | |||
5144ef9679 | |||
9c1d954bfd | |||
8aa724bd69 | |||
d7e3dee2af | |||
075df46572 | |||
e77af7d6ca | |||
c7caa3049c | |||
ccab7f01a2 |
39
README.md
39
README.md
@ -1,12 +1,34 @@
|
||||
[](https://cloud.tencent.com/act/cps/redirect?redirect=1052&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console)
|
||||
[](https://cloud.tencent.com/act/cps/redirect?redirect=1052&cps_key=736e609d66e0ac4e57813316cec6fd0b&from=console)
|
||||
|
||||
# 小说精品屋
|
||||
|
||||
#### 项目文档
|
||||
#### 新项目:小说精品屋-plus(推荐)
|
||||
|
||||
通用文档:[点击前往]( http://www.java2nb.com/article/5.html )
|
||||
小说精品屋-plus致力于打造一个完整的可商用、可学习的小说门户平台。小说精品屋-plus是在小说精品屋的基础上,重新进行了数据库设计、代码重构和功能增强,提升了程序整体的可读性和性能,增加了很多商用特性。
|
||||
|
||||
非JAVA开发参考安装文档:[点击前往]( https://my.oschina.net/java2nb/blog/3145593 )
|
||||
Gitee仓库地址: https://gitee.com/xiongxyang/novel-plus
|
||||
|
||||
GitHub仓库地址: https://github.com/201206030/novel-plus
|
||||
|
||||
#### 新项目:小说精品屋-微服务版(推荐)
|
||||
|
||||
基于小说精品屋-plus构建的Spring Cloud 微服务小说门户平台,可用于学习和商用。
|
||||
|
||||
Gitee仓库地址: https://gitee.com/xiongxyang/novel-cloud
|
||||
|
||||
GitHub仓库地址: https://github.com/201206030/novel-cloud
|
||||
|
||||
#### 前言
|
||||
|
||||
安装前请先阅读完此文档,了解项目基础配置和模块功能,再根据安装文档安装项目,避免一些不必要的错误。
|
||||
|
||||
#### 安装文档
|
||||
|
||||
源码安装文档(适合有一定技术基础的人):[点击前往](https://my.oschina.net/java2nb/blog/3145593)
|
||||
|
||||
包安装文档(适合非技术人员):[点击前往](https://my.oschina.net/java2nb/blog/3146627)
|
||||
|
||||
宝塔安装教程:[点击前往](https://www.daniao.org/7822.html )
|
||||
|
||||
#### 项目介绍
|
||||
|
||||
@ -105,7 +127,7 @@ novel-admin :平台后台管理系统源码(独立项目,按需安装)
|
||||
|
||||

|
||||
|
||||
#### 安装教程
|
||||
#### 安装说明
|
||||
|
||||
数据库安装:
|
||||
|
||||
@ -119,7 +141,7 @@ novel-admin :平台后台管理系统源码(独立项目,按需安装)
|
||||
1. 运行script/crawlbook/crawlbook.bat脚本文件。(适用于本地多机器运行)
|
||||
2. 安装后台管理系统后,打开爬虫管理菜单,点击爬虫运行按钮。(适用于线上环境运行,会占用较多服务器资源)
|
||||
|
||||
平台后台管理系统安装(独立项目,按需安装) :
|
||||
平台后台管理系统安装(独立项目,按需安装)(已停止维护,爬虫功能请使用crawlbook.bat) :
|
||||
|
||||
1. 修改application.yml文件中数据库配置。
|
||||
|
||||
@ -191,7 +213,7 @@ novel-admin :平台后台管理系统源码(独立项目,按需安装)
|
||||
|
||||
#### QQ交流群
|
||||
|
||||

|
||||

|
||||
|
||||
#### 捐赠支持
|
||||
|
||||
@ -203,6 +225,7 @@ novel-admin :平台后台管理系统源码(独立项目,按需安装)
|
||||
|
||||
| 捐赠者 | 金额 | 时间 |
|
||||
| :----- | :------- | :-------------------------- |
|
||||
| **阳 | ¥10.00 | 2020年03月06日 下午14点10分 |
|
||||
| *梦 | ¥66.00 | 2019年12月27日 下午21点39分 |
|
||||
| *金名 | ¥50.00 | 2019年12月27日 下午19点29分 |
|
||||
| *天气 | ¥300.00 | 2019年12月27日 上午10点13分 |
|
||||
@ -224,4 +247,4 @@ novel-admin :平台后台管理系统源码(独立项目,按需安装)
|
||||
|
||||
精品小说屋所有相关项目均已在开源中国公开,感兴趣的可进入[开源中国](https://www.oschina.net/p/fiction_house)按关键字`精品小说屋`搜索。
|
||||
|
||||
[](https://www.aliyun.com/minisite/goods?userCode=uf4nasee )
|
||||
[](https://www.aliyun.com/minisite/goods?userCode=uf4nasee )
|
BIN
assets/qq_group.png
Normal file
BIN
assets/qq_group.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
<groupId>xyz.zinglizingli</groupId>
|
||||
<artifactId>novel-front</artifactId>
|
||||
<version>2.3.0.beta</version>
|
||||
<version>2.5.0.beta</version>
|
||||
<name>novel-front</name>
|
||||
<description>小说精品楼-前台web网站</description>
|
||||
|
||||
|
@ -7,12 +7,14 @@ import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableCaching
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@MapperScan({"xyz.zinglizingli.*.mapper"})
|
||||
@ServletComponentScan
|
||||
public class BookApplication {
|
||||
|
@ -0,0 +1,27 @@
|
||||
package xyz.zinglizingli.books.core.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import xyz.zinglizingli.books.core.crawl.BaseHtmlCrawlSource;
|
||||
import xyz.zinglizingli.books.core.crawl.BiquCrawlSource;
|
||||
|
||||
/**
|
||||
* @author 11797
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class CrawlBiquwoConfig {
|
||||
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "biquwo.crawlsource") // prefix值必须是application.yml中对应属性的前缀
|
||||
@ConditionalOnProperty(prefix = "crawl.website",name = "type",havingValue = "6")
|
||||
public BaseHtmlCrawlSource biquwoCrawlSource() {
|
||||
return new BiquCrawlSource();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,4 +7,5 @@ public class CacheKeyConstans {
|
||||
public static final String EMAIL_URL_PREFIX_KEY = "emailUrlPrefixKey";
|
||||
public static final String RANDOM_NEWS_CONTENT_KEY = "randomNewsContentKey";
|
||||
public static final String REC_BOOK_LIST_KEY = "recBookListKey";
|
||||
public static final String BOOK_NUMBER_KEY= "bookNumberKey";
|
||||
}
|
||||
|
@ -3,15 +3,14 @@ package xyz.zinglizingli.books.core.crawl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import xyz.zinglizingli.books.core.utils.Constants;
|
||||
import xyz.zinglizingli.books.mapper.BookParseLogMapper;
|
||||
import xyz.zinglizingli.books.po.*;
|
||||
import xyz.zinglizingli.books.service.BookService;
|
||||
import xyz.zinglizingli.books.core.utils.CatUtil;
|
||||
import xyz.zinglizingli.common.utils.ExcutorUtils;
|
||||
import xyz.zinglizingli.common.cache.CommonCacheUtil;
|
||||
import xyz.zinglizingli.common.utils.RestTemplateUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -28,6 +27,12 @@ public class BiquCrawlSource extends BaseHtmlCrawlSource {
|
||||
@Autowired
|
||||
private BookService bookService;
|
||||
|
||||
@Autowired
|
||||
private CommonCacheUtil cacheUtil;
|
||||
|
||||
@Value("${books.maxNum}")
|
||||
private Integer maxNumBooks;
|
||||
|
||||
@Override
|
||||
public void parse() {
|
||||
|
||||
@ -65,7 +70,7 @@ public class BiquCrawlSource extends BaseHtmlCrawlSource {
|
||||
|
||||
String bookName = bookNameMatch.group(1);
|
||||
|
||||
bookService.addBookParseLog(bookUrl, bookName, score);
|
||||
bookService.addBookParseLog(bookUrl, bookName, score, (byte) 10);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -168,8 +173,11 @@ public class BiquCrawlSource extends BaseHtmlCrawlSource {
|
||||
|
||||
//查询该书籍已存在目录号
|
||||
Map<Integer, BookIndex> hasIndexs = bookService.queryIndexByBookNameAndAuthor(bookName, author);
|
||||
//查询数据库书籍数量
|
||||
long bookNumber = bookService.queryBookNumber();
|
||||
|
||||
//更新和插入分别开,此处只做更新
|
||||
if (hasIndexs.size() > 0) {
|
||||
if (hasIndexs.size() > 0 || bookNumber < maxNumBooks) {
|
||||
while (isFindIndex) {
|
||||
BookIndex hasIndex = hasIndexs.get(indexNum);
|
||||
String indexName = indexListMatch.group(2);
|
||||
|
@ -66,6 +66,7 @@ public class StartListener implements ServletContextListener {
|
||||
|
||||
log.info("updateBooks执行中。。。。。。。。。。。。");
|
||||
crawlSource.update();
|
||||
Thread.sleep(2000);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
@ -42,13 +42,16 @@ public class Network2LocalPicSchedule {
|
||||
|
||||
log.info("Network2LocalPicSchedule。。。。。。。。。。。。");
|
||||
|
||||
|
||||
Integer offset = 0, limit = 100;
|
||||
List<Book> networkPicBooks;
|
||||
do {
|
||||
networkPicBooks = bookService.queryNetworkPicBooks(limit, offset);
|
||||
for (Book book : networkPicBooks) {
|
||||
bookService.updateBook(book, book.getId());
|
||||
try {
|
||||
bookService.networkPicToLocal(book);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
offset += limit;
|
||||
} while (networkPicBooks.size() > 0);
|
||||
|
@ -27,4 +27,15 @@ public interface BookParseLogMapper {
|
||||
int updateByPrimaryKeySelective(BookParseLog record);
|
||||
|
||||
int updateByPrimaryKey(BookParseLog record);
|
||||
|
||||
/**
|
||||
* 增加小说更新次数
|
||||
*
|
||||
* @param logs*/
|
||||
void addBookUpdateCount(List<BookParseLog> logs);
|
||||
|
||||
/**
|
||||
* 查询解析日志
|
||||
* */
|
||||
List<BookParseLog> queryBookParseLogs();
|
||||
}
|
@ -13,6 +13,10 @@ public class BookParseLog {
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private Byte priority;
|
||||
|
||||
private Byte updateCount;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -52,4 +56,20 @@ public class BookParseLog {
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public Byte getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(Byte priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public Byte getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public void setUpdateCount(Byte updateCount) {
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
}
|
@ -424,6 +424,126 @@ public class BookParseLogExample {
|
||||
addCriterion("create_time not between", value1, value2, "createTime");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityIsNull() {
|
||||
addCriterion("priority is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityIsNotNull() {
|
||||
addCriterion("priority is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityEqualTo(Byte value) {
|
||||
addCriterion("priority =", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityNotEqualTo(Byte value) {
|
||||
addCriterion("priority <>", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityGreaterThan(Byte value) {
|
||||
addCriterion("priority >", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityGreaterThanOrEqualTo(Byte value) {
|
||||
addCriterion("priority >=", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityLessThan(Byte value) {
|
||||
addCriterion("priority <", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityLessThanOrEqualTo(Byte value) {
|
||||
addCriterion("priority <=", value, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityIn(List<Byte> values) {
|
||||
addCriterion("priority in", values, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityNotIn(List<Byte> values) {
|
||||
addCriterion("priority not in", values, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityBetween(Byte value1, Byte value2) {
|
||||
addCriterion("priority between", value1, value2, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPriorityNotBetween(Byte value1, Byte value2) {
|
||||
addCriterion("priority not between", value1, value2, "priority");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountIsNull() {
|
||||
addCriterion("update_count is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountIsNotNull() {
|
||||
addCriterion("update_count is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountEqualTo(Byte value) {
|
||||
addCriterion("update_count =", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountNotEqualTo(Byte value) {
|
||||
addCriterion("update_count <>", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountGreaterThan(Byte value) {
|
||||
addCriterion("update_count >", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountGreaterThanOrEqualTo(Byte value) {
|
||||
addCriterion("update_count >=", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountLessThan(Byte value) {
|
||||
addCriterion("update_count <", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountLessThanOrEqualTo(Byte value) {
|
||||
addCriterion("update_count <=", value, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountIn(List<Byte> values) {
|
||||
addCriterion("update_count in", values, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountNotIn(List<Byte> values) {
|
||||
addCriterion("update_count not in", values, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountBetween(Byte value1, Byte value2) {
|
||||
addCriterion("update_count between", value1, value2, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateCountNotBetween(Byte value1, Byte value2) {
|
||||
addCriterion("update_count not between", value1, value2, "updateCount");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tk.mybatis.orderbyhelper.OrderByHelper;
|
||||
@ -53,10 +54,9 @@ public class BookService {
|
||||
private String picSavePath;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存章节目录和内容
|
||||
* */
|
||||
*/
|
||||
public void saveBookAndIndexAndContent(Book book, List<BookIndex> bookIndex, List<BookContent> bookContent) {
|
||||
//解决内部调用事物不生效的问题
|
||||
BookService bookService = SpringUtil.getBean(BookService.class);
|
||||
@ -125,7 +125,6 @@ public class BookService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -133,7 +132,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 更新书籍
|
||||
* */
|
||||
*/
|
||||
public void updateBook(Book book, Long bookId) {
|
||||
book.setId(bookId);
|
||||
String picSrc = book.getPicUrl();
|
||||
@ -149,11 +148,25 @@ public class BookService {
|
||||
bookMapper.updateByPrimaryKeySelective(book);
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络图片转本地
|
||||
*
|
||||
* @param book
|
||||
*/
|
||||
public void networkPicToLocal(Book book) {
|
||||
try {
|
||||
book.setPicUrl(FileUtil.network2Local(book.getPicUrl(), picSavePath));
|
||||
bookMapper.updateByPrimaryKeySelective(book);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量插入章节目录表和章节内容表(自动修复错误章节)
|
||||
* */
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void insertIndexListAndContentList(List<BookIndex> newBookIndexList, List<BookContent> newContentList) {
|
||||
long start = System.currentTimeMillis();
|
||||
@ -178,7 +191,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 生成随机访问次数
|
||||
* */
|
||||
*/
|
||||
private Long generateVisitCount(Float score) {
|
||||
int baseNum = (int) (score * 100);
|
||||
return Long.parseLong(baseNum + new Random().nextInt(1000) + "");
|
||||
@ -205,10 +218,9 @@ public class BookService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询书籍的基础数据
|
||||
* */
|
||||
*/
|
||||
public Book queryBaseInfo(Long bookId) {
|
||||
|
||||
return bookMapper.selectByPrimaryKey(bookId);
|
||||
@ -216,7 +228,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询最新更新的书籍列表
|
||||
* */
|
||||
*/
|
||||
public List<BookIndex> queryNewIndexList(Long bookId) {
|
||||
PageHelper.startPage(1, 15);
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
@ -228,7 +240,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询书籍目录列表
|
||||
* */
|
||||
*/
|
||||
public List<BookIndex> queryAllIndexList(Long bookId) {
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
example.createCriteria().andBookIdEqualTo(bookId);
|
||||
@ -238,7 +250,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询书籍章节内容
|
||||
* */
|
||||
*/
|
||||
public BookContent queryBookContent(Long bookId, Integer indexNum) {
|
||||
BookContent content = (BookContent) cacheUtil.getObject(CacheKeyConstans.BOOK_CONTENT_KEY_PREFIX + "_" + bookId + "_" + indexNum);
|
||||
if (content == null) {
|
||||
@ -255,7 +267,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 增加访问次数
|
||||
* */
|
||||
*/
|
||||
public void addVisitCount(Long bookId, String userId, Integer indexNum) {
|
||||
|
||||
bookMapper.addVisitCount(bookId);
|
||||
@ -268,7 +280,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询章节名
|
||||
* */
|
||||
*/
|
||||
public String queryIndexNameByBookIdAndIndexNum(Long bookId, Integer indexNum) {
|
||||
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
@ -282,7 +294,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询最大和最小章节号
|
||||
* */
|
||||
*/
|
||||
public List<Integer> queryMaxAndMinIndexNum(Long bookId) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
@ -320,11 +332,9 @@ public class BookService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存弹幕
|
||||
* */
|
||||
*/
|
||||
public void sendBullet(Long contentId, String bullet) {
|
||||
|
||||
ScreenBullet screenBullet = new ScreenBullet();
|
||||
@ -337,7 +347,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询弹幕
|
||||
* */
|
||||
*/
|
||||
public List<ScreenBullet> queryBullet(Long contentId) {
|
||||
|
||||
ScreenBulletExample example = new ScreenBulletExample();
|
||||
@ -350,7 +360,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询章节内容
|
||||
* */
|
||||
*/
|
||||
public String queryContentList(Long bookId, int count) {
|
||||
BookContentExample example = new BookContentExample();
|
||||
example.createCriteria().andBookIdEqualTo(bookId).andIndexNumEqualTo(count);
|
||||
@ -359,7 +369,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询章节数
|
||||
* */
|
||||
*/
|
||||
public int countIndex(Long bookId) {
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
example.createCriteria().andBookIdEqualTo(bookId);
|
||||
@ -367,11 +377,9 @@ public class BookService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 查询前一章节和后一章节号
|
||||
* */
|
||||
*/
|
||||
public List<Integer> queryPreAndNextIndexNum(Long bookId, Integer indexNum) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
BookIndexExample example = new BookIndexExample();
|
||||
@ -398,14 +406,14 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询推荐书籍数据
|
||||
* */
|
||||
*/
|
||||
public List<Book> queryRecBooks(List<Map<String, String>> configMap) {
|
||||
return bookMapper.queryRecBooks(configMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理数据库中无效数据
|
||||
* */
|
||||
*/
|
||||
public void clearInvilidData() {
|
||||
|
||||
//清除无效内容
|
||||
@ -422,14 +430,15 @@ public class BookService {
|
||||
* 查询网络图片的小说
|
||||
*
|
||||
* @param limit
|
||||
* @param offset*/
|
||||
* @param offset
|
||||
*/
|
||||
public List<Book> queryNetworkPicBooks(Integer limit, Integer offset) {
|
||||
return bookMapper.queryNetworkPicBooks(limit, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过图片名查询小说数量
|
||||
* */
|
||||
*/
|
||||
public int countByPicName(String fileName) {
|
||||
BookExample bookExample = new BookExample();
|
||||
bookExample.createCriteria().andPicUrlLike('%' + fileName + '%');
|
||||
@ -438,8 +447,8 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 添加解析日志
|
||||
* */
|
||||
public void addBookParseLog(String bookUrl, String bookName, Float score) {
|
||||
*/
|
||||
public void addBookParseLog(String bookUrl, String bookName, Float score, Byte priority) {
|
||||
BookParseLogExample example = new BookParseLogExample();
|
||||
example.createCriteria().andBookUrlEqualTo(bookUrl).andCreateTimeGreaterThan(new Date(System.currentTimeMillis() - 1000 * 60 * 60));
|
||||
if (bookParseLogMapper.countByExample(example) == 0) {
|
||||
@ -447,6 +456,7 @@ public class BookService {
|
||||
bookParseLog.setBookUrl(bookUrl);
|
||||
bookParseLog.setBookName(bookName);
|
||||
bookParseLog.setScore(score);
|
||||
bookParseLog.setPriority(priority);
|
||||
bookParseLog.setCreateTime(new Date());
|
||||
bookParseLogMapper.insertSelective(bookParseLog);
|
||||
}
|
||||
@ -454,18 +464,26 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询解析日志
|
||||
* */
|
||||
*/
|
||||
public List<BookParseLog> queryBookParseLogs() {
|
||||
PageHelper.startPage(1,100);
|
||||
BookParseLogExample example = new BookParseLogExample();
|
||||
example.setOrderByClause("create_time desc");
|
||||
List<BookParseLog> logs = bookParseLogMapper.selectByExample(example);
|
||||
List<BookParseLog> logs = bookParseLogMapper.queryBookParseLogs();
|
||||
if(logs.size()>0) {
|
||||
SpringUtil.getBean(BookService.class).addBookUpdateCount(logs);
|
||||
}
|
||||
return logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加小说更新次数
|
||||
*/
|
||||
@Async
|
||||
public void addBookUpdateCount(List<BookParseLog> logs) {
|
||||
bookParseLogMapper.addBookUpdateCount(logs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除已经成功更新的解析日志
|
||||
* */
|
||||
*/
|
||||
public void deleteBookParseLogs(List<Long> successLogIds) {
|
||||
if (successLogIds.size() > 0) {
|
||||
BookParseLogExample example = new BookParseLogExample();
|
||||
@ -476,7 +494,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询书籍是否存在
|
||||
* */
|
||||
*/
|
||||
public Boolean hasBook(String bookName, String author) {
|
||||
BookExample example = new BookExample();
|
||||
example.createCriteria().andBookNameEqualTo(bookName).andAuthorEqualTo(author);
|
||||
@ -485,7 +503,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 查询分类更新时间映射信息
|
||||
* */
|
||||
*/
|
||||
public Map<Integer, Date> queryLastUpdateTime() {
|
||||
List<BookUpdateTimeLog> list = bookUpdateTimeLogMapper.selectByExample(new BookUpdateTimeLogExample());
|
||||
|
||||
@ -495,7 +513,7 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 更新分类时间日志
|
||||
* */
|
||||
*/
|
||||
public void updateBookUpdateTimeLog(Map<Integer, Date> cat2Date) {
|
||||
if (cat2Date.size() > 0) {
|
||||
Set<Map.Entry<Integer, Date>> entries = cat2Date.entrySet();
|
||||
@ -512,9 +530,22 @@ public class BookService {
|
||||
|
||||
/**
|
||||
* 删除已经成功更新的解析日志
|
||||
* */
|
||||
*/
|
||||
public void deleteBookParseLog(Long id) {
|
||||
bookParseLogMapper.deleteByPrimaryKey(id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据库书籍数量
|
||||
*/
|
||||
public int queryBookNumber() {
|
||||
|
||||
Integer bookNumber = (Integer) cacheUtil.getObject(CacheKeyConstans.BOOK_NUMBER_KEY);
|
||||
if (bookNumber == null) {
|
||||
bookNumber = bookMapper.countByExample(new BookExample());
|
||||
cacheUtil.setObject(CacheKeyConstans.BOOK_NUMBER_KEY, bookNumber, 60 * 5);
|
||||
}
|
||||
return bookNumber;
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,9 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import xyz.zinglizingli.books.core.config.SeoConfig;
|
||||
import xyz.zinglizingli.books.po.Book;
|
||||
import xyz.zinglizingli.books.po.BookContent;
|
||||
import xyz.zinglizingli.books.po.BookIndex;
|
||||
import xyz.zinglizingli.books.po.ScreenBullet;
|
||||
import xyz.zinglizingli.books.po.*;
|
||||
import xyz.zinglizingli.books.service.BookService;
|
||||
import xyz.zinglizingli.books.service.UserService;
|
||||
import xyz.zinglizingli.books.vo.BookVO;
|
||||
@ -50,6 +44,27 @@ public class BookController {
|
||||
private final CommonCacheUtil commonCacheUtil;
|
||||
|
||||
|
||||
/**
|
||||
* 单本小说提交页
|
||||
* */
|
||||
@RequestMapping("submit.html")
|
||||
public String bookSubmitPage(){
|
||||
return "books/book_submit";
|
||||
}
|
||||
|
||||
/**
|
||||
* 单本小说提交
|
||||
* */
|
||||
@RequestMapping(method = RequestMethod.POST,value = "submit")
|
||||
@ResponseBody
|
||||
public Map<String, Object> bookSubmit(String bookUrl, String bookName, Float score){
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
bookService.addBookParseLog(bookUrl, bookName, score, (byte) 5);
|
||||
result.put("code", 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 精品小说搜索页
|
||||
@ -306,7 +321,7 @@ public class BookController {
|
||||
@ResponseBody
|
||||
public Map<String, Object> sendBullet(@RequestParam("contentId") Long contentId, @RequestParam("bullet") String bullet) {
|
||||
Map<String, Object> result = new HashMap<>(2);
|
||||
bookService.sendBullet(contentId, bullet);
|
||||
bookService.sendBullet(contentId, bullet.replaceAll("<", "<").replaceAll(">", ">"));
|
||||
result.put("code", 1);
|
||||
result.put("desc", "ok");
|
||||
return result;
|
||||
|
@ -86,3 +86,20 @@ biquge:
|
||||
intro-pattern: class="review">([^/]+)</p>
|
||||
catalog-url-pattern: <a\s+href="(/ddk\d+/all.html)">查看完整目录</a>
|
||||
catalog-pattern: <dd>\s*<a\s+href="(\d+\.html)"\s+title="([^"]+)">([^<]+)</a>\s*</dd>
|
||||
|
||||
|
||||
biquwo:
|
||||
crawlsource:
|
||||
index-url: http://m.biquwo.net
|
||||
list-page-url: http://m.biquwo.net/sort{0}/0/{1}.html
|
||||
book-url-pattern: href="/(dudu/\d+/\d+)/"
|
||||
score-pattern: <div\s+class="score">(\d+\.\d+)分</div>
|
||||
book-name-pattern: <p class="title">([^/]+)</p>
|
||||
author-pattern: 作者:([^/]+)<
|
||||
status-pattern: 状态:([^/]+)</li>
|
||||
cat-pattern: 类别:([^/]+)</li>
|
||||
update-time-pattern: 更新:(\d+-\d+-\d+\s\d+:\d+:\d+)</a>
|
||||
pic-pattern: <img src="([^>]+)"\s+onerror="this.src=
|
||||
intro-pattern: class="review">([^<]+)</p>
|
||||
catalog-url-pattern: <a\s+href="(/dudu/\d+/\d+/all\.html)">查看完整目录</a>
|
||||
catalog-pattern: <a\s+style=""\s+href="(/dudu/\d+/\d+/\d+\.html)">([^/]+)</a>
|
@ -1,7 +1,7 @@
|
||||
#网站配置
|
||||
website:
|
||||
#网站名
|
||||
name: 小说精品屋
|
||||
name: 精品小说楼
|
||||
#域名
|
||||
domain: https://www.xinshumen.com
|
||||
#页面配置
|
||||
|
@ -83,18 +83,20 @@ books:
|
||||
lowestScore: 6.0
|
||||
#小说的更新间隔(分)
|
||||
updatePeriod: 1
|
||||
#爬取小说数量
|
||||
maxNum: 300000
|
||||
|
||||
#爬取的网站名称类型 1:笔趣岛 ,2:笔趣塔,3:顶点小说 ,4:百书斋 更多网站解析中,敬请期待
|
||||
#爬取的网站名称类型 1:笔趣岛 ,2:笔趣塔,3:顶点小说 ,4:百书斋,6: 笔趣窝 更多网站解析中,敬请期待
|
||||
crawl:
|
||||
website:
|
||||
type: 4
|
||||
type: 6
|
||||
|
||||
|
||||
|
||||
|
||||
pic:
|
||||
save:
|
||||
type: 1 #图片保存方式, 1不保存,使用网络图片 ,2本地保存
|
||||
type: 2 #图片保存方式, 1不保存,使用网络图片 ,2本地保存
|
||||
path: /var/pic #图片保存路径
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@
|
||||
<property name="enableSubPackages" value="false" />
|
||||
</javaClientGenerator>
|
||||
|
||||
<table tableName="book_update_time_log"/>
|
||||
<table tableName="book_parse_log"/>
|
||||
|
||||
<!-- 指定数据库表 -->
|
||||
<!--<table schema="jly" tableName="job_position" domainObjectName="JobPositionTest"/>-->
|
||||
|
@ -7,6 +7,8 @@
|
||||
<result column="book_name" property="bookName" jdbcType="VARCHAR"/>
|
||||
<result column="score" property="score" jdbcType="REAL"/>
|
||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
|
||||
<result column="priority" property="priority" jdbcType="TINYINT"/>
|
||||
<result column="update_count" property="updateCount" jdbcType="TINYINT"/>
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
@ -26,7 +28,8 @@
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
|
||||
<foreach collection="criterion.value" item="listItem" open="(" close=")"
|
||||
separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
@ -55,7 +58,8 @@
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
|
||||
<foreach collection="criterion.value" item="listItem" open="(" close=")"
|
||||
separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
@ -67,9 +71,10 @@
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, book_url, book_name, score, create_time
|
||||
id, book_url, book_name, score, create_time, priority, update_count
|
||||
</sql>
|
||||
<select id="selectByExample" resultMap="BaseResultMap" parameterType="xyz.zinglizingli.books.po.BookParseLogExample" >
|
||||
<select id="selectByExample" resultMap="BaseResultMap"
|
||||
parameterType="xyz.zinglizingli.books.po.BookParseLogExample">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
@ -101,9 +106,11 @@
|
||||
</delete>
|
||||
<insert id="insert" parameterType="xyz.zinglizingli.books.po.BookParseLog">
|
||||
insert into book_parse_log (id, book_url, book_name,
|
||||
score, create_time)
|
||||
score, create_time, priority,
|
||||
update_count)
|
||||
values (#{id,jdbcType=BIGINT}, #{bookUrl,jdbcType=VARCHAR}, #{bookName,jdbcType=VARCHAR},
|
||||
#{score,jdbcType=REAL}, #{createTime,jdbcType=TIMESTAMP})
|
||||
#{score,jdbcType=REAL}, #{createTime,jdbcType=TIMESTAMP}, #{priority,jdbcType=TINYINT},
|
||||
#{updateCount,jdbcType=TINYINT})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="xyz.zinglizingli.books.po.BookParseLog">
|
||||
insert into book_parse_log
|
||||
@ -123,6 +130,12 @@
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
<if test="priority != null">
|
||||
priority,
|
||||
</if>
|
||||
<if test="updateCount != null">
|
||||
update_count,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
@ -140,9 +153,16 @@
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
<if test="priority != null">
|
||||
#{priority,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="updateCount != null">
|
||||
#{updateCount,jdbcType=TINYINT},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="xyz.zinglizingli.books.po.BookParseLogExample" resultType="java.lang.Integer" >
|
||||
<select id="countByExample" parameterType="xyz.zinglizingli.books.po.BookParseLogExample"
|
||||
resultType="java.lang.Integer">
|
||||
select count(*) from book_parse_log
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause"/>
|
||||
@ -166,6 +186,12 @@
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
<if test="record.priority != null">
|
||||
priority = #{record.priority,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="record.updateCount != null">
|
||||
update_count = #{record.updateCount,jdbcType=TINYINT},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause"/>
|
||||
@ -177,7 +203,9 @@
|
||||
book_url = #{record.bookUrl,jdbcType=VARCHAR},
|
||||
book_name = #{record.bookName,jdbcType=VARCHAR},
|
||||
score = #{record.score,jdbcType=REAL},
|
||||
create_time = #{record.createTime,jdbcType=TIMESTAMP}
|
||||
create_time = #{record.createTime,jdbcType=TIMESTAMP},
|
||||
priority = #{record.priority,jdbcType=TINYINT},
|
||||
update_count = #{record.updateCount,jdbcType=TINYINT}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause"/>
|
||||
</if>
|
||||
@ -197,6 +225,12 @@
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
<if test="priority != null">
|
||||
priority = #{priority,jdbcType=TINYINT},
|
||||
</if>
|
||||
<if test="updateCount != null">
|
||||
update_count = #{updateCount,jdbcType=TINYINT},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
@ -205,7 +239,30 @@
|
||||
set book_url = #{bookUrl,jdbcType=VARCHAR},
|
||||
book_name = #{bookName,jdbcType=VARCHAR},
|
||||
score = #{score,jdbcType=REAL},
|
||||
create_time = #{createTime,jdbcType=TIMESTAMP}
|
||||
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||
priority = #{priority,jdbcType=TINYINT},
|
||||
update_count = #{updateCount,jdbcType=TINYINT}
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
|
||||
<update id="addBookUpdateCount">
|
||||
|
||||
update book_parse_log set update_count = update_count + 1
|
||||
where id in
|
||||
<foreach collection="list" item="log" separator="," open="(" close=")">
|
||||
#{log.id}
|
||||
</foreach>
|
||||
|
||||
</update>
|
||||
|
||||
|
||||
<select id="queryBookParseLogs" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List"/>
|
||||
from book_parse_log
|
||||
where update_count <![CDATA[ < ]]> 5
|
||||
order by priority asc,create_time desc
|
||||
limit 100
|
||||
|
||||
</select>
|
||||
</mapper>
|
@ -195,7 +195,7 @@
|
||||
}
|
||||
//发送弹幕
|
||||
function sendBullet(){
|
||||
var bullet = $("#screenBulletText").val();
|
||||
var bullet = $("#screenBulletText").val().replace(/</g, "<").replace(/>/g, ">");
|
||||
var contentId = $("#contentIdHidden").val();
|
||||
if (bullet && contentId) {
|
||||
if(bullet.length > 100){
|
||||
|
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>小说提交</title>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body id="read" >
|
||||
|
||||
</div>
|
||||
|
||||
<div style="height: 50px;line-height: 50px;text-align: center" class="layui-header header header-doc layui-bg-cyan">
|
||||
|
||||
<div style="float: left;margin-left: 10px">
|
||||
<a href="javascript:history.go(-1)">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i></a>
|
||||
</div>
|
||||
<b class="layui-icon">单本小说提交</b>
|
||||
<div style="float: right;margin-right: 10px"><a href="/">
|
||||
<i style="font-size: 20px;color: #92B8B1;" class="layui-icon"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 800px;padding: 20px;border: 1px solid #eee;">
|
||||
<form class="layui-form" action="">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">详情页Url:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookUrl" name="bookUrl" required lay-verify="required" placeholder="请输入源站小说详情页Url" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说名:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1" >
|
||||
<input type="text" id="bookName" name="bookName" required lay-verify="required" placeholder="请输入小说名" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">小说评分:</label>
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md3 layui-col-lg1">
|
||||
<input type="number" id="score" name="score" required lay-verify="required" placeholder="请输入小说评分" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit lay-filter="formDemo">提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
|
||||
<a name="buttom"></a>
|
||||
</body>
|
||||
<div th:replace="common/js :: js"></div>
|
||||
|
||||
|
||||
<script>
|
||||
//Demo
|
||||
layui.use('form', function(){
|
||||
var form = layui.form;
|
||||
|
||||
//监听提交
|
||||
form.on('submit(formDemo)', function(){
|
||||
$.post("/book/submit",{"bookUrl":$("#bookUrl").val(),"bookName":$("#bookName").val(),"score":$("#score").val()},function (data) {
|
||||
if(data.code == 1 ){
|
||||
layer.alert("提交成功,任务排队中,请过一段时间后再搜索查看");
|
||||
}else{
|
||||
layer.alert("提交失败");
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
283
novel-front/src/main/resources/templates/books/index.html
Normal file
283
novel-front/src/main/resources/templates/books/index.html
Normal file
@ -0,0 +1,283 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
|
||||
<title>精品小说楼</title>
|
||||
|
||||
<meta name="keywords" content="精品小说楼,精品小说,弹幕网站,弹幕,弹幕小说网站,免费小说,小说阅读,小说排行,轻小说,txt小说下载,电子书下载,动漫轻小说,日本轻小说">
|
||||
|
||||
<meta name="description"
|
||||
content="精品小说楼是国内优秀的小说弹幕网站,精品小说楼提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。">
|
||||
|
||||
<meta property="og:type" content="novel_index"/>
|
||||
<meta property="og:title" content="精品小说楼"/>
|
||||
<meta property="og:description"
|
||||
content="精品小说楼是国内优秀的小说弹幕网站,精品小说楼提供海量热门网络小说,日本轻小说,国产轻小说,动漫小说,轻小说在线阅读和TXT小说下载,致力于网络精品小说的收集,智能计算小说评分,打造小说精品排行榜,致力于无广告无弹窗的小说阅读环境。"/>
|
||||
|
||||
<div th:include="common/css :: css"></div>
|
||||
|
||||
<style>
|
||||
|
||||
.line-limit-length {
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
text-overflow: ellipsis;
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
}
|
||||
|
||||
.layui-nav .layui-nav-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
body ul.layui-nav li.layui-nav-item a {
|
||||
display: block;
|
||||
transition: all .3s;
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?2cf01edbc2b27cd3a143e17948167d77";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<!-- 你的HTML代码 -->
|
||||
<a name="top"></a>
|
||||
<ul class="layui-nav" lay-filter="" style="padding:0 36px;text-align: center">
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=1">玄幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=2">修真小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=3">都市小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=4">历史小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=6">网游小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=5">科幻小说</a></li>
|
||||
<li class="layui-nav-item"><a href="/book/search?catId=7">女频小说</a></li>
|
||||
<li class="layui-nav-item"><a>完本小说</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/search?bookStatus=完成">全部小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/search?bookStatus=完成&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item"><a>小说排行</a>
|
||||
<dl class="layui-nav-child"> <!-- 二级菜单 -->
|
||||
<dd><a href="/book/search?sortBy=score">全部小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=1">玄幻小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=2">修真小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=3">都市小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=4">历史小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=6">网游小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=5">科幻小说</a></dd>
|
||||
<dd><a href="/book/search?sortBy=score&catId=7">女频小说</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
|
||||
<div class="layui-col-xs10 layui-col-sm10 layui-col-md11 layui-col-lg11" style="padding-top:1%">
|
||||
<input id="title" type="text" name="title" required lay-verify="required" placeholder="请输入书名·作者"
|
||||
autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
<div class="layui-col-xs1" style="padding: 1%">
|
||||
<button onclick="searchBooks()" class="layui-btn" lay-submit lay-filter="formDemo">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="layui-collapse">
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">本站推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
|
||||
<div class="layui-container" style="padding: 0px">
|
||||
|
||||
<div class="layui-row" style="text-align: center">
|
||||
<span th:each="recBook : ${recBooks}">
|
||||
<a th:href="'/book/' + ${recBook.id} + '.html'">
|
||||
<div style="padding: 1%" class="layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4">
|
||||
<img style=" width:80%; height:auto; max-width:100%; max-height:100%;"
|
||||
th:src="${recBook.picUrl}"/>
|
||||
<br/>
|
||||
<span th:text="${recBook.bookName}"></span>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-colla-item">
|
||||
<h2 class="layui-colla-title">热门小说推荐</h2>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container">
|
||||
<div class="layui-row">
|
||||
<div style="margin-bottom: 5px" class="layui-col-xs12 layui-col-sm6 layui-col-md4 layui-col-lg4"
|
||||
th:each="hotBook : ${hotBooks}">
|
||||
<a th:href="'/book/' + ${hotBook.id} + '.html'">
|
||||
<div class="layui-col-xs5 layui-col-sm4 layui-col-md4 layui-col-lg4">
|
||||
<img style=" width:100px; height:125px;"
|
||||
th:src="${hotBook.picUrl}"/>
|
||||
</div>
|
||||
<div class="layui-col-xs5 layui-col-sm6 layui-col-md6 layui-col-lg6">
|
||||
<ul>
|
||||
<li class="line-limit-length" style="font-weight: bold"
|
||||
th:text="${hotBook.bookName}"></li>
|
||||
<li th:text="'作者:'+ ${hotBook.author}"></li>
|
||||
<li style="width: 180px;height:40px;overflow: hidden"
|
||||
th:text="'简介:'+ ${hotBook.bookDesc}"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="font-style: italic;color: red"
|
||||
class="layui-col-xs2 layui-col-sm2 layui-col-md2 layui-col-lg2"
|
||||
th:text="${hotBook.score} + '分'"></div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!--<div th:each="hotBook : ${hotBooks}" style="margin-top: 1%"
|
||||
class="layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6">
|
||||
<a th:href="'/book/'+${hotBook.id}+'.html'">
|
||||
<div class="layui-col-xs5 layui-col-sm3 layui-col-md3 layui-col-lg3">
|
||||
<img style=" width:100px; height:125px;"
|
||||
th:src="${hotBook.picUrl}"/>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-xs7 layui-col-sm6 layui-col-md7 layui-col-lg7"
|
||||
style="float: left;padding-right: 10px">
|
||||
<div><b th:text="${hotBook.bookName}"></b></div>
|
||||
<div class="layui-col-xs8 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="'作者:'+ ${hotBook.author}"></div>
|
||||
<div class="layui-col-xs3 layui-col-sm2 layui-col-md1 layui-col-lg1" style="text-align: right;">
|
||||
<b><i style="color: red"
|
||||
th:text="${hotBook.score} + '分'"></i></b></div>
|
||||
</div>
|
||||
<div class="layui-elip layui-col-xs12 layui-col-sm9 layui-col-md10 layui-col-lg10 layui-col-sm9 layui-col-md10 layui-col-lg10"
|
||||
th:text="${hotBook.bookDesc}">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</a>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-colla-item"><a href="javascript:moreNewBooks()">
|
||||
<h2 class="layui-colla-title">最近更新小说
|
||||
<div style="float: right; margin-right: 20px"><i style="font-size: 14px;"
|
||||
class="layui-icon">更多</i>
|
||||
</div>
|
||||
</h2>
|
||||
</a>
|
||||
<div class="layui-colla-content layui-show">
|
||||
|
||||
<div class="layui-container" style="padding-left: 2px;padding-right: 5px">
|
||||
<div class="layui-row">
|
||||
<div th:each="newBook,bookStat : ${newBooks}" style="padding-bottom: 30px"
|
||||
class="layui-col-xs12 layui-col-sm6 layui-col-md6 layui-col-lg6">
|
||||
|
||||
<a th:href="'/book/'+${newBook.id}+'.html'">
|
||||
<div class="line-limit-length layui-col-xs8 layui-col-sm6 layui-col-md6 layui-col-lg6"><b
|
||||
th:text="${bookStat.index}+1+'.'+${newBook.bookName}"></b> - <span class="layui-elip"
|
||||
th:text="${newBook.author}"></span>
|
||||
</div>
|
||||
<div class="layui-col-sm3 layui-col-md3 layui-col-lg3"
|
||||
style="color: #FF5722;float: right;margin-right:5px"><i
|
||||
th:text="${#dates.format(newBook.updateTime, 'MM-dd HH:mm')}"></i></div>
|
||||
|
||||
<div style="clear: both"></div>
|
||||
<div style="padding-left: 5px;padding-top: 5px"
|
||||
class="layui-elip layui-col-md11 layui-col-sm11 layui-col-lg11"
|
||||
th:text="'简介:'+ ${newBook.bookDesc}">
|
||||
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="common/footer :: footer">
|
||||
</div>
|
||||
<div th:replace="common/js :: js">
|
||||
</div>
|
||||
|
||||
<script src="/js/wap_collect.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var bp = document.createElement('script');
|
||||
var curProtocol = window.location.protocol.split(':')[0];
|
||||
if (curProtocol === 'https') {
|
||||
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
|
||||
} else {
|
||||
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
|
||||
}
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(bp, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
function moreNewBooks(event) {
|
||||
window.location.href = "/book/search";
|
||||
}
|
||||
|
||||
function searchBooks() {
|
||||
var keywords = $("#title").val();
|
||||
window.location.href = "/book/search?keyword=" + encodeURI(keywords);
|
||||
}
|
||||
|
||||
function toMyCollect() {
|
||||
var token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
window.location.href = "/book/search?token=" + token;
|
||||
} else {
|
||||
window.location.href = "/user/login.html";
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -7,9 +7,10 @@ mybatis:
|
||||
type-aliases-package: xyz.zinglizingli.books.po
|
||||
configuration: {log-impl: org.apache.ibatis.logging.stdout.StdOutImpl}
|
||||
mysql: {charset: utf8mb4}
|
||||
books: {lowestScore: 9.0}
|
||||
books: {lowestScore: 6.0}
|
||||
crawl:
|
||||
website: {type: '4'}
|
||||
patten: '1'
|
||||
website: {type: 6}
|
||||
soft-novel: '0'
|
||||
manhua: '0'
|
||||
logging: {config: 'classpath:logback-boot.xml'}
|
||||
|
Binary file not shown.
1
sql/2020-04-21.sql
Normal file
1
sql/2020-04-21.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table book_parse_log add column `priority` TINYINT(2) not null default 10 ;
|
1
sql/2020-04-22.sql
Normal file
1
sql/2020-04-22.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table book_parse_log add column `update_count` TINYINT(2) not null default 0 ;
|
@ -1,23 +1,4 @@
|
||||
/*
|
||||
Navicat MySQL Data Transfer
|
||||
|
||||
Source Server : aliyun_books
|
||||
Source Server Version : 80018
|
||||
Source Host : 47.106.243.172:3306
|
||||
Source Database : books
|
||||
|
||||
Target Server Type : MYSQL
|
||||
Target Server Version : 80018
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 2019-11-15 06:10:36
|
||||
*/
|
||||
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for `book`
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `book`;
|
||||
CREATE TABLE `book` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
@ -1042,3 +1023,8 @@ INSERT INTO `book_update_time_log` VALUES ('6', '6', NOW());
|
||||
INSERT INTO `book_update_time_log` VALUES ('7', '7', NOW());
|
||||
|
||||
ALTER TABLE book_parse_log drop INDEX uq_key_bookurl;
|
||||
|
||||
alter table book_parse_log add column `priority` TINYINT(2) not null default 10 ;
|
||||
|
||||
alter table book_parse_log add column `update_count` TINYINT(2) not null default 0 ;
|
||||
|
||||
|
Reference in New Issue
Block a user