一、个人简介
💖💖作者:计算机编程果茶熊 💙💙个人简介:曾长期从事计算机专业培训教学,担任过编程老师,同时本人也热爱上课教学,擅长Java、微信小程序、Python、Golang、安卓Android等多个IT方向。会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。平常喜欢分享一些自己开发中遇到的问题的解决办法,也喜欢交流技术,大家有技术代码这一块的问题可以问我! 💛💛想说的话:感谢大家的关注与支持! 💜💜 网站实战项目 安卓/小程序实战项目 大数据实战项目 计算机毕业设计选题 💕💕文末获取源码联系计算机编程果茶熊
二、系统介绍
开发语言:Java+Python 数据库:MySQL 系统架构:B/S 后端框架:SpringBoot(Spring+SpringMVC+Mybatis)+Django 前端:Vue+HTML+CSS+JavaScript+jQuery
本系统是一个基于爬虫技术的热门图书推荐系统,采用Java和Python双语言架构设计,为用户提供智能化的图书发现和社交交流平台。系统通过网络爬虫技术自动采集各大图书平台的热门图书信息,结合用户行为数据和图书属性特征,运用推荐算法为用户精准推送符合个人偏好的图书资源。系统集成了完整的用户管理体系,支持用户注册、登录、个人信息维护等基础功能,同时建立了丰富的图书信息数据库,包含图书详情、评分、分类等多维度信息。为增强用户体验,系统构建了图书论坛模块,用户可以在不同的论坛分类中发表读书心得、参与讨论交流,形成良好的阅读社区氛围。系统还设置了举报机制和系统管理功能,确保平台内容的健康性和系统运行的稳定性。整体架构采用前后端分离的B/S模式,前端使用Vue框架配合ElementUI组件库打造现代化的用户界面,后端基于Spring Boot框架提供RESTful API服务,数据存储采用MySQL数据库,确保系统的高性能和可扩展性。
三、视频解说
四、部分功能展示
五、部分代码展示
import org.apache.spark.sql.SparkSession;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class BookRecommendationService {
@Autowired
private BookMapper bookMapper;
@Autowired
private UserBehaviorMapper userBehaviorMapper;
@Autowired
private RedisTemplate redisTemplate;
private SparkSession spark = SparkSession.builder().appName("BookRecommendation").master("local[*]").getOrCreate();
public List<Book> getPersonalizedRecommendations(Long userId, int limit) {
List<UserBehavior> userBehaviors = userBehaviorMapper.getUserBehaviors(userId);
Map<String, Double> categoryPreferences = calculateCategoryPreferences(userBehaviors);
List<String> preferredAuthors = extractPreferredAuthors(userBehaviors);
Set<Long> readBookIds = userBehaviors.stream().map(UserBehavior::getBookId).collect(Collectors.toSet());
List<Book> candidateBooks = bookMapper.getCandidateBooks(readBookIds);
List<Book> scoredBooks = new ArrayList<>();
for (Book book : candidateBooks) {
double score = calculateRecommendationScore(book, categoryPreferences, preferredAuthors);
book.setRecommendationScore(score);
scoredBooks.add(book);
}
return scoredBooks.stream()
.sorted((b1, b2) -> Double.compare(b2.getRecommendationScore(), b1.getRecommendationScore()))
.limit(limit)
.collect(Collectors.toList());
}
private double calculateRecommendationScore(Book book, Map<String, Double> categoryPreferences, List<String> preferredAuthors) {
double categoryScore = categoryPreferences.getOrDefault(book.getCategory(), 0.0) * 0.4;
double authorScore = preferredAuthors.contains(book.getAuthor()) ? 0.3 : 0.0;
double ratingScore = (book.getAverageRating() / 5.0) * 0.2;
double popularityScore = Math.log(book.getViewCount() + 1) / Math.log(10000) * 0.1;
return categoryScore + authorScore + ratingScore + popularityScore;
}
}
@Service
public class BookCrawlerService {
@Autowired
private BookMapper bookMapper;
@Autowired
private HttpClientUtil httpClientUtil;
public void crawlHotBooks() {
List<String> targetUrls = Arrays.asList(
"https://book.douban.com/chart",
"https://www.amazon.cn/gp/bestsellers/books",
"https://book.jd.com/hot"
);
for (String url : targetUrls) {
try {
String htmlContent = httpClientUtil.get(url);
List<Book> books = parseBookInfo(htmlContent, url);
for (Book book : books) {
if (bookMapper.findByIsbn(book.getIsbn()) == null) {
book.setCrawlTime(new Date());
book.setSource(extractDomain(url));
bookMapper.insert(book);
} else {
updateBookHotness(book);
}
}
} catch (Exception e) {
logCrawlError(url, e.getMessage());
}
}
}
private List<Book> parseBookInfo(String htmlContent, String sourceUrl) {
List<Book> books = new ArrayList<>();
Document doc = Jsoup.parse(htmlContent);
Elements bookElements = doc.select(".book-item, .product-item");
for (Element element : bookElements) {
Book book = new Book();
book.setTitle(element.select(".title, .book-title").text());
book.setAuthor(element.select(".author").text());
book.setPrice(parsePrice(element.select(".price").text()));
book.setImageUrl(element.select("img").attr("src"));
String ratingText = element.select(".rating, .score").text();
book.setAverageRating(parseRating(ratingText));
book.setDescription(element.select(".description, .summary").text());
book.setPublisher(element.select(".publisher").text());
books.add(book);
}
return books;
}
private void updateBookHotness(Book book) {
Book existingBook = bookMapper.findByIsbn(book.getIsbn());
existingBook.setViewCount(existingBook.getViewCount() + 1);
existingBook.setHotnessScore(calculateHotnessScore(existingBook));
existingBook.setLastCrawlTime(new Date());
bookMapper.update(existingBook);
}
}
@Service
public class ForumService {
@Autowired
private ForumPostMapper forumPostMapper;
@Autowired
private ForumCategoryMapper forumCategoryMapper;
@Autowired
private ReportMapper reportMapper;
public ForumPost createPost(ForumPostRequest request, Long userId) {
validatePostContent(request.getContent());
ForumCategory category = forumCategoryMapper.findById(request.getCategoryId());
if (category == null) {
throw new BusinessException("论坛分类不存在");
}
ForumPost post = new ForumPost();
post.setTitle(request.getTitle());
post.setContent(filterSensitiveContent(request.getContent()));
post.setCategoryId(request.getCategoryId());
post.setUserId(userId);
post.setCreateTime(new Date());
post.setStatus(PostStatus.NORMAL);
post.setViewCount(0);
post.setLikeCount(0);
post.setReplyCount(0);
forumPostMapper.insert(post);
updateCategoryPostCount(request.getCategoryId());
return post;
}
private String filterSensitiveContent(String content) {
List<String> sensitiveWords = Arrays.asList("违法", "欺诈", "色情", "暴力");
String filteredContent = content;
for (String word : sensitiveWords) {
filteredContent = filteredContent.replaceAll(word, "***");
}
return filteredContent;
}
public List<ForumPost> getHotPosts(int limit) {
Date sevenDaysAgo = new Date(System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000);
List<ForumPost> recentPosts = forumPostMapper.findByCreateTimeAfter(sevenDaysAgo);
return recentPosts.stream()
.sorted((p1, p2) -> {
double score1 = calculateHotScore(p1);
double score2 = calculateHotScore(p2);
return Double.compare(score2, score1);
})
.limit(limit)
.collect(Collectors.toList());
}
private double calculateHotScore(ForumPost post) {
long timeDiff = System.currentTimeMillis() - post.getCreateTime().getTime();
double timeWeight = Math.exp(-timeDiff / (24 * 60 * 60 * 1000.0));
return (post.getLikeCount() * 2 + post.getReplyCount() * 1.5 + post.getViewCount() * 0.1) * timeWeight;
}
}
六、部分文档展示
七、END
💕💕文末获取源码联系计算机编程果茶熊