前言
昨天没发是一直在写项目,想逻辑。
大概是一个小说爬取网,能动态编写小说源来爬取。现在已经是实现了爬取逻辑,还进行了多线程优化。
1. 爬取不同源小说同时进行
没一个小说源大概得给我这个页面的解析
这个方法是哪一个url 什么规则 分页爬取
getBookInfoList(crawlerWebTypeUrl.getUrl(), rule.getCategory(), 1, 2);
在只需要加个线程池把这个任务扔进去就完成了第一层不同源
2. 二层优化
拿到以上那个图片中的小说集合 可以进行分段
public static <T> List<List<T>> divideList(List<T> originalList, int numberOfChunks) {
List<List<T>> dividedList = new ArrayList<>();
int chunkSize = (int) Math.ceil((double) originalList.size() / numberOfChunks);
int index = 0;
for (int i = 0; i < numberOfChunks; i++) {
if (index >= originalList.size()) {
break;
}
List<T> chunk = originalList.subList(index, Math.min(index + chunkSize, originalList.size()));
dividedList.add(chunk);
index += chunkSize;
}
return dividedList;
}
3. 为每一个小说是否分章爬取
把图片中的所有章节获取 这里也可以分章节爬取 如分2个线程 那么一个线程负责一半嘛
在章节获取时还可以优化比如 每个线程是批量上传的如爬取100个小说后再进行插入数据库操作。
批量上传这里就有个问题,数据库id怎么办我采用的是批量拉取id
@Override //通过乐观锁
public BookChapterIdVO getId(int size) {
BookChapterId bookChapterId = bookChapterIdMapper.selectById(1);
while (bookChapterIdMapper.update(null, Wrappers.lambdaUpdate(BookChapterId.class)
.set(BookChapterId::getVersion, bookChapterId.getVersion() + 1)
.set(BookChapterId::getBookChapterId, bookChapterId.getBookChapterId() + size)
.eq(BookChapterId::getVersion, bookChapterId.getVersion())
.eq(BookChapterId::getId, bookChapterId.getId())
) != 1) {
bookChapterId = bookChapterIdMapper.selectById(1);
}
return new BookChapterIdVO(bookChapterId.getBookChapterId(), bookChapterId.getBookChapterId() + size);
}
这是数据库
通过乐观锁的机制多线程安全获取ID批量拉取
4. 自己的思考
如何进行文章更新,可以写一个定时任务在每天12点的时候拉取所有正在连载的小说,去爬取这个连载小说的最新章节是否在小说库中,直到获取章节存在为止。
还可以进行分库分表优化爬取小说
以上运用的线程模型大概是 n个数据源---m个小说段---k个小说章节