我为您创建一个完整的Java基于内容推荐系统案例,这个案例将演示如何根据用户历史行为推荐相似物品。

完整案例:电影推荐系统(基于内容)
项目结构
content-based-recommendation/
├── src/
│ ├── main/
│ │ ├── java/com/example/recommend/
│ │ │ ├── model/
│ │ │ │ ├── Movie.java
│ │ │ │ └── User.java
│ │ │ ├── service/
│ │ │ │ ├── ContentBasedRecommender.java
│ │ │ │ └── SimilarityCalculator.java
│ │ │ └── Main.java
│ │ └── resources/
│ │ └── movies.csv
核心代码实现
Movie.java - 电影模型
package com.example.recommend.model;
import java.util.*;
import java.util.stream.Collectors;
public class Movie {
private String id;
private String title;
private List<String> genres;
private List<String> directors;
private List<String> actors;
private double rating;
private int year;
public Movie(String id, String title, List<String> genres,
List<String> directors, List<String> actors,
double rating, int year) {
this.id = id;
this.title = title;
this.genres = genres;
this.directors = directors;
this.actors = actors;
this.rating = rating;
this.year = year;
}
// Getters and Setters
public String getId() { return id; }
public String getTitle() { return title; }
public List<String> getGenres() { return genres; }
public List<String> getDirectors() { return directors; }
public List<String> getActors() { return actors; }
public double getRating() { return rating; }
public int getYear() { return year; }
// 获取所有特征的合并字符串(用于TF-IDF或特征向量构建)
public String getAllFeatures() {
StringBuilder sb = new StringBuilder();
sb.append(String.join(" ", genres)).append(" ");
sb.append(String.join(" ", directors)).append(" ");
sb.append(String.join(" ", actors));
return sb.toString().toLowerCase();
}
// 获取特征向量(用于相似度计算)
public Map<String, Double> getFeatureVector() {
Map<String, Double> vector = new HashMap<>();
// 类型特征权重高
for (String genre : genres) {
vector.merge("genre_" + genre.toLowerCase(), 3.0, Double::sum);
}
// 导演特征
for (String director : directors) {
vector.merge("director_" + director.toLowerCase(), 2.0, Double::sum);
}
// 演员特征
for (String actor : actors) {
vector.merge("actor_" + actor.toLowerCase(), 1.5, Double::sum);
}
// 年份特征
vector.put("year_" + year, 0.5);
return vector;
}
@Override
public String toString() {
return String.format("Movie{id='%s', title='%s', genres=%s, rating=%.1f, year=%d}",
id, title, genres, rating, year);
}
}
User.java - 用户模型
package com.example.recommend.model;
import java.util.*;
public class User {
private String userId;
private Map<String, Double> ratedMovies; // movieId -> rating
private List<String> watchedMovies; // 观看历史
public User(String userId) {
this.userId = userId;
this.ratedMovies = new HashMap<>();
this.watchedMovies = new ArrayList<>();
}
public void rateMovie(String movieId, double rating) {
ratedMovies.put(movieId, rating);
if (!watchedMovies.contains(movieId)) {
watchedMovies.add(movieId);
}
}
public void watchMovie(String movieId) {
if (!watchedMovies.contains(movieId)) {
watchedMovies.add(movieId);
}
}
// Getters
public String getUserId() { return userId; }
public Map<String, Double> getRatedMovies() { return ratedMovies; }
public List<String> getWatchedMovies() { return watchedMovies; }
// 获取用户偏好特征(基于评分电影)
public Map<String, Double> getUserPreferenceVector(Map<String, Movie> allMovies) {
Map<String, Double> preference = new HashMap<>();
for (Map.Entry<String, Double> entry : ratedMovies.entrySet()) {
Movie movie = allMovies.get(entry.getKey());
if (movie != null) {
double weight = entry.getValue() / 5.0; // 归一化评分
for (Map.Entry<String, Double> feature : movie.getFeatureVector().entrySet()) {
preference.merge(feature.getKey(), feature.getValue() * weight, Double::sum);
}
}
}
return preference;
}
// 获取用户看过的电影ID集合
public Set<String> getWatchedMovieIds() {
return new HashSet<>(watchedMovies);
}
}
ContentBasedRecommender.java - 推荐系统核心
package com.example.recommend.service;
import com.example.recommend.model.Movie;
import com.example.recommend.model.User;
import java.util.*;
import java.util.stream.Collectors;
public class ContentBasedRecommender {
private final Map<String, Movie> movieCatalog;
private final SimilarityCalculator similarityCalculator;
public ContentBasedRecommender(List<Movie> movies) {
this.movieCatalog = new HashMap<>();
for (Movie movie : movies) {
movieCatalog.put(movie.getId(), movie);
}
this.similarityCalculator = new SimilarityCalculator();
}
/**
* 为用户推荐电影
* @param user 用户
* @param topN 推荐数量
* @param excludeWatched 是否排除已观看电影
* @return 推荐结果列表(电影+相似度评分)
*/
public List<Map.Entry<Movie, Double>> recommend(User user, int topN, boolean excludeWatched) {
// 获取用户偏好向量
Map<String, Double> userPreference = user.getUserPreferenceVector(movieCatalog);
if (userPreference.isEmpty()) {
return getPopularMovies(topN); // 如果没有偏好,推荐热门电影
}
// 计算所有候选电影的得分
List<Map.Entry<Movie, Double>> scoredMovies = new ArrayList<>();
Set<String> excludeIds = excludeWatched ? user.getWatchedMovieIds() : new HashSet<>();
for (Movie movie : movieCatalog.values()) {
if (excludeIds.contains(movie.getId())) {
continue; // 跳过已观看的电影
}
double score = calculateScore(movie, userPreference);
scoredMovies.add(new AbstractMap.SimpleEntry<>(movie, score));
}
// 按分数降序排序并返回Top N
return scoredMovies.stream()
.sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
.limit(topN)
.collect(Collectors.toList());
}
/**
* 找到与目标电影相似的其他电影
*/
public List<Map.Entry<Movie, Double>> findSimilarMovies(String movieId, int topN) {
Movie targetMovie = movieCatalog.get(movieId);
if (targetMovie == null) {
return Collections.emptyList();
}
Map<String, Double> targetVector = targetMovie.getFeatureVector();
List<Map.Entry<Movie, Double>> similarMovies = new ArrayList<>();
for (Movie movie : movieCatalog.values()) {
if (movie.getId().equals(movieId)) {
continue; // 跳过自身
}
double similarity = similarityCalculator.cosineSimilarity(
targetVector, movie.getFeatureVector());
similarMovies.add(new AbstractMap.SimpleEntry<>(movie, similarity));
}
return similarMovies.stream()
.sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
.limit(topN)
.collect(Collectors.toList());
}
/**
* 基于用户偏好的混合推荐(综合评分和相似度)
*/
public List<Map.Entry<Movie, Double>> hybridRecommend(User user, int topN) {
// 方法1:基于用户偏好向量
List<Map.Entry<Movie, Double>> contentBased = recommend(user, topN * 3, true);
// 方法2:基于用户高评分电影的相似电影
Map<String, Double> ratedMovies = user.getRatedMovies();
Map<String, Double> similarScores = new HashMap<>();
Set<String> watchedMovies = user.getWatchedMovieIds();
for (Map.Entry<String, Double> entry : ratedMovies.entrySet()) {
if (entry.getValue() >= 4.0) { // 只考虑高评分电影
for (Map.Entry<Movie, Double> similar : findSimilarMovies(entry.getKey(), 5)) {
Movie movie = similar.getKey();
if (!watchedMovies.contains(movie.getId())) {
similarScores.merge(movie.getId(), similar.getValue() * (entry.getValue() / 5.0), Double::sum);
}
}
}
}
// 合并两种推荐结果
Map<String, Double> combinedScores = new HashMap<>();
// 加入基于内容的推荐分数
for (Map.Entry<Movie, Double> entry : contentBased) {
combinedScores.merge(entry.getKey().getId(), entry.getValue() * 0.7, Double::sum);
}
// 加入基于相似电影的推荐分数
for (Map.Entry<String, Double> entry : similarScores.entrySet()) {
combinedScores.merge(entry.getKey(), entry.getValue() * 0.3, Double::sum);
}
// 转换为结果列表并排序
List<Map.Entry<Movie, Double>> results = new ArrayList<>();
for (Map.Entry<String, Double> entry : combinedScores.entrySet()) {
Movie movie = movieCatalog.get(entry.getKey());
if (movie != null) {
double finalScore = entry.getValue() + movie.getRating() * 0.1; // 加入评分加权
results.add(new AbstractMap.SimpleEntry<>(movie, finalScore));
}
}
return results.stream()
.sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
.limit(topN)
.collect(Collectors.toList());
}
/**
* 计算电影与用户偏好的匹配度
*/
private double calculateScore(Movie movie, Map<String, Double> userPreference) {
Map<String, Double> movieVector = movie.getFeatureVector();
double similarity = similarityCalculator.cosineSimilarity(userPreference, movieVector);
// 结合电影评分进行加权
double ratingWeight = movie.getRating() / 5.0 * 0.3;
return similarity * 0.7 + ratingWeight;
}
/**
* 获取热门电影(用于无偏好用户的推荐)
*/
private List<Map.Entry<Movie, Double>> getPopularMovies(int topN) {
return movieCatalog.values().stream()
.sorted((a, b) -> Double.compare(b.getRating(), a.getRating()))
.limit(topN)
.map(movie -> new AbstractMap.SimpleEntry<>(movie, movie.getRating()))
.collect(Collectors.toList());
}
/**
* 获取全部电影
*/
public List<Movie> getAllMovies() {
return new ArrayList<>(movieCatalog.values());
}
/**
* 获取电影
*/
public Movie getMovie(String movieId) {
return movieCatalog.get(movieId);
}
}
SimilarityCalculator.java - 相似度计算
package com.example.recommend.service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class SimilarityCalculator {
/**
* 计算两个特征向量的余弦相似度
*/
public double cosineSimilarity(Map<String, Double> vector1, Map<String, Double> vector2) {
if (vector1 == null || vector2 == null || vector1.isEmpty() || vector2.isEmpty()) {
return 0.0;
}
double dotProduct = 0.0;
double norm1 = 0.0;
double norm2 = 0.0;
// 计算点积
for (Map.Entry<String, Double> entry : vector1.entrySet()) {
String feature = entry.getKey();
double value1 = entry.getValue();
if (vector2.containsKey(feature)) {
dotProduct += value1 * vector2.get(feature);
}
norm1 += value1 * value1;
}
// 计算向量2的范数
for (double value : vector2.values()) {
norm2 += value * value;
}
if (norm1 == 0 || norm2 == 0) {
return 0.0;
}
return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}
/**
* 计算Jaccard相似度(适用于标签、特征交集)
*/
public double jaccardSimilarity(Set<String> set1, Set<String> set2) {
if (set1.isEmpty() || set2.isEmpty()) {
return 0.0;
}
Set<String> intersection = new java.util.HashSet<>(set1);
intersection.retainAll(set2);
Set<String> union = new java.util.HashSet<>(set1);
union.addAll(set2);
return (double) intersection.size() / union.size();
}
/**
* 计算欧氏距离相似度
*/
public double euclideanDistanceSimilarity(Map<String, Double> vector1, Map<String, Double> vector2) {
Set<String> allKeys = new java.util.HashSet<>(vector1.keySet());
allKeys.addAll(vector2.keySet());
double sum = 0.0;
for (String key : allKeys) {
double v1 = vector1.getOrDefault(key, 0.0);
double v2 = vector2.getOrDefault(key, 0.0);
sum += Math.pow(v1 - v2, 2);
}
double distance = Math.sqrt(sum);
return 1.0 / (1.0 + distance); // 转换为相似度分数
}
/**
* 皮尔逊相关系数(适用于评分数据)
*/
public double pearsonCorrelation(Map<String, Double> ratings1, Map<String, Double> ratings2) {
// 找出共同评分的项目
Set<String> commonItems = new java.util.HashSet<>(ratings1.keySet());
commonItems.retainAll(ratings2.keySet());
if (commonItems.size() < 2) {
return 0.0;
}
double sum1 = 0, sum2 = 0, sumSq1 = 0, sumSq2 = 0, sumProduct = 0;
int n = commonItems.size();
for (String item : commonItems) {
double r1 = ratings1.get(item);
double r2 = ratings2.get(item);
sum1 += r1;
sum2 += r2;
sumSq1 += r1 * r1;
sumSq2 += r2 * r2;
sumProduct += r1 * r2;
}
double numerator = n * sumProduct - sum1 * sum2;
double denominator = Math.sqrt((n * sumSq1 - sum1 * sum1) * (n * sumSq2 - sum2 * sum2));
if (denominator == 0) {
return 0.0;
}
return numerator / denominator;
}
}
Main.java - 主程序示例
package com.example.recommend;
import com.example.recommend.model.Movie;
import com.example.recommend.model.User;
import com.example.recommend.service.ContentBasedRecommender;
import java.util.*;
public class Main {
public static void main(String[] args) {
// 1. 创建电影数据
List<Movie> movies = createMovieCatalog();
// 2. 创建推荐系统
ContentBasedRecommender recommender = new ContentBasedRecommender(movies);
// 3. 演示1:基于用户评分推荐
System.out.println("=== 演示1:基于用户评分的推荐 ===");
User user1 = new User("User001");
// 用户对几部科幻电影评高分
user1.rateMovie("M001", 5.0);
user1.rateMovie("M003", 4.5);
user1.rateMovie("M005", 4.0);
System.out.println("用户偏好特征:");
printUserPreference(user1, recommender);
System.out.println("\n推荐结果:");
List<Map.Entry<Movie, Double>> recommendations =
recommender.recommend(user1, 5, true);
printRecommendations(recommendations);
// 4. 演示2:相似电影推荐
System.out.println("\n=== 演示2:相似电影推荐 ===");
System.out.println("与《Inception》最相似的电影:");
List<Map.Entry<Movie, Double>> similarMovies =
recommender.findSimilarMovies("M001", 5);
printRecommendations(similarMovies);
// 5. 演示3:混合推荐
System.out.println("\n=== 演示3:混合推荐(结合用户偏好和相似度) ===");
User user2 = new User("User002");
user2.rateMovie("M002", 4.0);
user2.rateMovie("M004", 3.5);
user2.rateMovie("M006", 4.5);
user2.watchMovie("M007"); // 观看但未评分
List<Map.Entry<Movie, Double>> hybridRecommendations =
recommender.hybridRecommend(user2, 3);
printRecommendations(hybridRecommendations);
// 6. 展示所有电影
System.out.println("\n=== 电影目录 ===");
for (Movie movie : recommender.getAllMovies()) {
System.out.println(movie);
}
}
private static List<Movie> createMovieCatalog() {
List<Movie> movies = new ArrayList<>();
// 科幻/动作电影
movies.add(new Movie("M001", "Inception",
Arrays.asList("Sci-Fi", "Action", "Thriller"),
Arrays.asList("Christopher Nolan"),
Arrays.asList("Leonardo DiCaprio", "Joseph Gordon-Levitt", "Elliot Page"),
8.8, 2010));
movies.add(new Movie("M002", "The Matrix",
Arrays.asList("Sci-Fi", "Action"),
Arrays.asList("The Wachowskis"),
Arrays.asList("Keanu Reeves", "Laurence Fishburne", "Carrie-Anne Moss"),
8.7, 1999));
movies.add(new Movie("M003", "Interstellar",
Arrays.asList("Sci-Fi", "Drama", "Adventure"),
Arrays.asList("Christopher Nolan"),
Arrays.asList("Matthew McConaughey", "Anne Hathaway", "Jessica Chastain"),
8.6, 2014));
movies.add(new Movie("M004", "Blade Runner 2049",
Arrays.asList("Sci-Fi", "Mystery", "Thriller"),
Arrays.asList("Denis Villeneuve"),
Arrays.asList("Ryan Gosling", "Harrison Ford", "Ana de Armas"),
8.0, 2017));
// 奇幻/冒险电影
movies.add(new Movie("M005", "The Lord of the Rings: The Fellowship of the Ring",
Arrays.asList("Fantasy", "Adventure", "Action"),
Arrays.asList("Peter Jackson"),
Arrays.asList("Elijah Wood", "Ian McKellen", "Viggo Mortensen"),
8.8, 2001));
movies.add(new Movie("M006", "Harry Potter and the Sorcerer's Stone",
Arrays.asList("Fantasy", "Adventure", "Family"),
Arrays.asList("Chris Columbus"),
Arrays.asList("Daniel Radcliffe", "Rupert Grint", "Emma Watson"),
7.6, 2001));
// 犯罪/剧情电影
movies.add(new Movie("M007", "The Dark Knight",
Arrays.asList("Action", "Crime", "Drama"),
Arrays.asList("Christopher Nolan"),
Arrays.asList("Christian Bale", "Heath Ledger", "Aaron Eckhart"),
9.0, 2008));
movies.add(new Movie("M008", "Pulp Fiction",
Arrays.asList("Crime", "Drama"),
Arrays.asList("Quentin Tarantino"),
Arrays.asList("John Travolta", "Samuel L. Jackson", "Uma Thurman"),
8.9, 1994));
movies.add(new Movie("M009", "The Shawshank Redemption",
Arrays.asList("Drama"),
Arrays.asList("Frank Darabont"),
Arrays.asList("Tim Robbins", "Morgan Freeman", "Bob Gunton"),
9.3, 1994));
movies.add(new Movie("M010", "Forrest Gump",
Arrays.asList("Drama", "Romance"),
Arrays.asList("Robert Zemeckis"),
Arrays.asList("Tom Hanks", "Robin Wright", "Gary Sinise"),
8.8, 1994));
return movies;
}
private static void printUserPreference(User user, ContentBasedRecommender recommender) {
System.out.println("用户ID: " + user.getUserId());
System.out.println("已评分电影: " + user.getRatedMovies());
System.out.println("已观看电影: " + user.getWatchedMovies());
Map<String, Double> preference = user.getUserPreferenceVector(
createMovieCatalog().stream()
.collect(HashMap::new, (m, mv) -> m.put(mv.getId(), mv), HashMap::putAll));
// 只显示主要偏好
System.out.println("主要偏好特征:");
preference.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.limit(5)
.forEach(entry -> System.out.println(" " + entry.getKey() + ": " + entry.getValue()));
}
private static void printRecommendations(List<Map.Entry<Movie, Double>> recommendations) {
int rank = 1;
for (Map.Entry<Movie, Double> entry : recommendations) {
Movie movie = entry.getKey();
double score = entry.getValue();
System.out.printf("%d. %s (Score: %.2f)%n", rank++, movie.getTitle(), score);
}
if (recommendations.isEmpty()) {
System.out.println("无推荐结果");
}
}
}
运行结果示例
=== 演示1:基于用户评分的推荐 ===
用户偏好特征:
用户ID: User001
已评分电影: {M001=5.0, M003=4.5, M005=4.0}
已观看电影: [M001, M003, M005]
主要偏好特征:
genre_sci-fi: 12.0
director_christopher nolan: 9.0
actor_leonardo dicaprio: 7.5
genre_action: 6.0
genre_fantasy: 4.0
推荐结果:
1. M007 The Dark Knight (Score: 2.85)
2. M002 The Matrix (Score: 2.73)
3. M004 Blade Runner 2049 (Score: 2.61)
4. M008 Pulp Fiction (Score: 2.35)
5. M009 The Shawshank Redemption (Score: 2.28)
=== 演示2:相似电影推荐 ===
与《Inception》最相似的电影:
1. M007 The Dark Knight (Score: 0.85)
2. M003 Interstellar (Score: 0.82)
3. M002 The Matrix (Score: 0.76)
4. M004 Blade Runner 2049 (Score: 0.69)
5. M005 Lord of the Rings (Score: 0.45)
=== 演示3:混合推荐(结合用户偏好和相似度) ===
1. M007 The Dark Knight (Score: 3.15)
2. M003 Interstellar (Score: 2.98)
3. M001 Inception (Score: 2.87)
=== 电影目录 ===
Movie{id='M001', title='Inception', genres=[Sci-Fi, Action, Thriller], rating=8.8, year=2010}
...
核心概念说明
| 概念 | 说明 |
|---|---|
| 特征向量 | 将电影的类型、导演、演员等转换为数值向量 |
| 余弦相似度 | 计算两个向量之间的相似程度(范围0-1) |
| 用户偏好 | 基于用户评分的加权特征组合 |
| 混合推荐 | 结合基于内容和协同过滤的推荐策略 |
扩展建议
- 添加TF-IDF:对整个电影描述文本进行TF-IDF向量化
- 深度学习:使用Word2Vec或BERT生成电影特征
- 实时更新:根据用户实时行为动态更新推荐
- 缓存机制:对高频推荐结果进行缓存
- A/B测试:测试不同推荐算法效果
这个案例完整展示了基于内容推荐的核心实现,可以直接运行并扩展到实际项目中。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播