基于豆瓣电影数据的类型预测模型开发

一、项目思路与数据准备

要预测豆瓣电影的类型,需要通过爬虫获取电影的特征数据(如导演、演员、剧情简介等),然后利用机器学习模型训练分类器。以下是完整实现方案:

二、数据爬取:获取豆瓣电影特征与类型
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
import re

# 配置请求头模拟浏览器访问
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}

def crawl_douban_movies():
    """爬取豆瓣电影数据,包括标题、导演、演员、剧情简介和类型"""
    all_movies = []
    # 遍历豆瓣电影分类页(以剧情片、喜剧片、动作片为例)
    categories = ['剧情', '喜剧', '动作']  # 可扩展更多类型
    for category in categories:
        for start in range(0, 200, 20):  # 每类爬取200部电影
            url = f'https://movie.douban.com/tag/#/sort/score/type/{category}?start={start}&limit=20'
            try:
                response = requests.get(url, headers=headers, timeout=10)
                response.raise_for_status()  # 检查请求是否成功
                soup = BeautifulSoup(response.text, 'lxml')
                
                # 提取电影列表
                movie_items = soup.find_all('div', class_='item-root')
                for item in movie_items:
                    try:
                        # 提取标题
                        title = item.find('span', class_='title').text.strip()
                        # 提取导演和演员
                        info = item.find('div', class_='abstract_2').text.strip()
                        director = re.search(r'导演: (.*?) ', info).group(1) if re.search(r'导演: (.*?) ', info) else ''
                        actors = re.search(r'主演: (.*)', info).group(1) if re.search(r'主演: (.*)', info) else ''
                        # 提取剧情简介
                        intro = item.find('div', class_='abstract_3').text.strip() if item.find('div', class_='abstract_3') else ''
                        # 记录类型
                        movie_type = category
                        
                        all_movies.append({
                            'title': title,
                            'director': director,
                            'actors': actors,
                            'intro': intro,
                            'type': movie_type
                        })
                        print(f"成功爬取: {title} - {movie_type}")
                    except Exception as e:
                        print(f"解析电影信息失败: {e}")
                
                # 随机延时避免反爬
                time.sleep(random.uniform(1, 3))
            except Exception as e:
                print(f"请求出错: {e}")
    
    # 保存为DataFrame
    df = pd.DataFrame(all_movies)
    df.to_csv('douban_movies.csv', index=False, encoding='utf-8-sig')
    return df

# 执行爬取(首次运行时取消注释)
# df = crawl_douban_movies()

# 直接加载已爬取数据(后续运行时使用)
df = pd.read_csv('douban_movies.csv')
print(f"已加载{len(df)}部电影数据")
三、数据预处理:特征提取与清洗
import nltk
import re
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split

# 下载英文停用词(中文停用词需自定义)
nltk.download('stopwords')
english_stopwords = set(stopwords.words('english'))
# 自定义中文停用词
chinese_stopwords = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'}

def preprocess_text(text):
    """文本预处理:清洗、分词、去停用词"""
    if not isinstance(text, str):
        return ''
    # 去除特殊字符和数字
    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z]', ' ', text)
    # 转换为小写
    text = text.lower()
    # 分词(简化处理,中文可使用jieba分词)
    words = re.findall(r'\w+', text)
    # 去除停用词
    filtered_words = [word for word in words if word not in english_stopwords and word not in chinese_stopwords]
    return ' '.join(filtered_words)

# 合并导演、演员和剧情简介作为特征文本
df['combined_features'] = df['director'] + ' ' + df['actors'] + ' ' + df['intro']
# 应用文本预处理
df['processed_features'] = df['combined_features'].apply(preprocess_text)

# 划分训练集和测试集
X = df['processed_features']
y = df['type']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 使用TF-IDF提取特征
vectorizer = TfidfVectorizer(max_features=1000, stop_words=chinese_stopwords.union(english_stopwords))
X_train_tfidf = vectorizer.fit_transform(X_train)
X_test_tfidf = vectorizer.transform(X_test)
print(f"TF-IDF特征维度: {X_train_tfidf.shape[1]}")
四、模型训练:多分类算法对比
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt

# 定义模型列表
models = {
    '随机森林': RandomForestClassifier(n_estimators=100, random_state=42),
    '支持向量机': SVC(probability=True, random_state=42),
    '逻辑回归': LogisticRegression(multi_class='multinomial', solver='lbfgs', random_state=42)
}

# 训练并评估模型
results = {}
for name, model in models.items():
    print(f"\n训练{name}模型...")
    model.fit(X_train_tfidf, y_train)
    y_pred = model.predict(X_test_tfidf)
    accuracy = accuracy_score(y_test, y_pred)
    results[name] = accuracy
    print(f"{name}准确率: {accuracy:.4f}")
    print("分类报告:")
    print(classification_report(y_test, y_pred))
    
    # 绘制混淆矩阵
    cm = confusion_matrix(y_test, y_pred)
    plt.figure(figsize=(10, 8))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
                xticklabels=sorted(df['type'].unique()), 
                yticklabels=sorted(df['type'].unique()))
    plt.xlabel('预测类型')
    plt.ylabel('真实类型')
    plt.title(f'{name}混淆矩阵')
    plt.tight_layout()
    plt.savefig(f'{name}_confusion_matrix.png')

# 比较模型性能
plt.figure(figsize=(10, 6))
plt.bar(results.keys(), results.values())
plt.xlabel('模型')
plt.ylabel('准确率')
plt.title('不同模型的电影类型预测准确率')
plt.tight_layout()
plt.savefig('model_comparison.png')
plt.show()

# 选择最佳模型(以随机森林为例)
best_model = RandomForestClassifier(n_estimators=100, random_state=42)
best_model.fit(X_train_tfidf, y_train)
五、模型应用:预测新电影类型
def predict_movie_type(movie_info):
    """预测新电影的类型"""
    # 预处理输入文本
    processed_info = preprocess_text(movie_info)
    # 转换为TF-IDF特征
    tfidf_features = vectorizer.transform([processed_info])
    # 预测类型
    predicted_type = best_model.predict(tfidf_features)[0]
    # 获取预测概率
    proba = best_model.predict_proba(tfidf_features)[0]
    proba_dict = {label: prob for label, prob in zip(best_model.classes_, proba)}
    # 按概率排序
    sorted_proba = sorted(proba_dict.items(), key=lambda x: x[1], reverse=True)
    
    print(f"\n===== 电影类型预测结果 =====")
    print(f"输入信息: {movie_info[:50]}...")
    print(f"预测类型: {predicted_type}")
    print("\n各类别概率:")
    for label, prob in sorted_proba:
        print(f"{label}: {prob:.4f}")
    
    return predicted_type, sorted_proba

# 示例:预测新电影类型
test_movie = "由诺兰导演,基里安·墨菲主演,讲述科学家通过梦境窃取机密的科幻故事,充满悬疑和烧脑情节。"
predict_movie_type(test_movie)

# 保存模型以便后续使用
import joblib
joblib.dump(best_model, 'movie_type_classifier.pkl')
joblib.dump(vectorizer, 'tfidf_vectorizer.pkl')
六、优化方向与注意事项

1. 数据增强:

◦ 爬取更多电影类型(如科幻、悬疑、爱情等)和样本数量(建议每类至少500部)

◦ 增加更多特征(如上映年份、国家/地区、评分等)

2. 文本处理优化:

◦ 中文文本使用jieba等专业分词工具

◦ 尝试Word2Vec、FastText等词向量模型替代TF-IDF

3. 模型升级:

◦ 尝试深度学习模型(如LSTM、BERT)处理文本序列

◦ 使用XGBoost、LightGBM等提升树模型提高分类精度

4. 合规与反爬:

◦ 爬取时控制频率(如添加随机延时),避免封禁IP

◦ 仅爬取公开数据,不涉及用户隐私信息

通过上述方案,可实现一个基于豆瓣电影数据的类型预测模型,该模型能根据电影的导演、演员和剧情简介等信息,智能判断其所属类型,准确率通常可达70%~85%(取决于数据质量和模型复杂度)。

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐