如何用Flask、Pandas搭建接收flag与userId的Python协同过滤推荐应用?
Hey there! As a fellow data scientist who’s built quick Flask apps for prototype projects, I’ll walk you through a complete, step-by-step solution tailored exactly to your needs—no prior HTML/Flask experience required. Let’s break this down into manageable parts:
First, install the required packages. Open your terminal and run:
pip install flask pandas scikit-learn
flask: For building the web app and handling formspandas: To work with your local user interest datascikit-learn: For implementing the cosine similarity-based collaborative filtering
Keep things clean with this folder setup (Flask requires the templates folder for HTML files):
topic_recommender/ ├── app.py # Core Flask app logic ├── templates/ # HTML pages │ ├── login.html # User login form │ └── recommendations.html # Recommendation display page └── user_data/ # Local Pandas-compatible data files ├── user_interests.csv # User-interest matrix └── topics.csv # List of topics to recommend
Let’s define sample data structures you can adapt to your real data:
user_interests.csv (User-Interest Matrix)
This file maps users to their interest scores (1-5, where higher = more interested):
userId,sports,tech,cooking,travel,art 1,5,3,1,4,2 2,2,5,4,1,3 3,3,2,5,3,4 4,4,4,2,5,1
topics.csv (Topic Lookup)
Links interest categories to human-readable topic names:
topic_id,topic_name 1,Weekend Mountain Hiking 2,AI Model Optimization 3,Authentic Italian Cooking 4,Backpacking Across Southeast Asia 5,Contemporary Art Gallery Tours
app.py) This is the core of your app—we’ll split it into logical sections with comments for clarity:
from flask import Flask, render_template, request, redirect, url_for import pandas as pd from sklearn.metrics.pairwise import cosine_similarity # Initialize Flask app app = Flask(__name__) # Load local data once when the app starts (avoids reloading on every request) user_interests_df = pd.read_csv('user_data/user_interests.csv') topics_df = pd.read_csv('user_data/topics.csv') # Map interest columns to topic names (adjust this to match your data!) interest_topic_map = { 'sports': 'Weekend Mountain Hiking', 'tech': 'AI Model Optimization', 'cooking': 'Authentic Italian Cooking', 'travel': 'Backpacking Across Southeast Asia', 'art': 'Contemporary Art Gallery Tours' } def generate_recommendations(user_id, filter_flag=None): """ Collaborative filtering logic: Find similar users and recommend topics the target user hasn't shown strong interest in """ # Create a matrix of user interests (exclude userId column) interest_matrix = user_interests_df.set_index('userId') # Get the target user's interest profile target_user_profile = interest_matrix.loc[user_id].values.reshape(1, -1) # Calculate cosine similarity between target user and all others user_similarities = cosine_similarity(interest_matrix, target_user_profile).flatten() # Get top 3 most similar users (exclude the user themselves) similar_user_indices = user_similarities.argsort()[-4:-1][::-1] similar_users = interest_matrix.iloc[similar_user_indices] # Average the interest scores of similar users avg_similar_user_interests = similar_users.mean(axis=0) # Filter out topics the target user already likes (score >=3) target_user_high_interests = interest_matrix.loc[user_id][interest_matrix.loc[user_id] >=3].index recommended_interests = avg_similar_user_interests.drop(target_user_high_interests).sort_values(ascending=False) # Map interest columns to topic names recommended_topics = [interest_topic_map[interest] for interest in recommended_interests.index] # Apply optional flag filter (e.g., "sports_only" to narrow recommendations) if filter_flag: filter_flag = filter_flag.lower() recommended_topics = [topic for topic in recommended_topics if filter_flag.split('_')[0] in topic.lower()] # Return top 3 recommendations return recommended_topics[:3] # Login route (handles both displaying the form and processing submissions) @app.route('/', methods=['GET', 'POST']) def login(): if request.method == 'POST': # Get form data user_flag = request.form.get('flag') user_id = request.form.get('userId') # Validate User ID exists in our data if not user_id.isdigit() or int(user_id) not in user_interests_df['userId'].values: return render_template('login.html', error="Invalid User ID—please enter a valid ID from your dataset.") # Generate recommendations user_recommendations = generate_recommendations(int(user_id), user_flag) # Redirect to recommendations page with data return redirect(url_for('show_recommendations', user_id=user_id, recs=','.join(user_recommendations))) # If it's a GET request, show the login form return render_template('login.html') # Recommendations display route @app.route('/recommendations') def show_recommendations(): # Retrieve data from the redirect request user_id = request.args.get('user_id') recommendations = request.args.get('recs').split(',') return render_template('recommendations.html', user_id=user_id, recommendations=recommendations) # Run the app if __name__ == '__main__': app.run(debug=True) # Debug mode auto-reloads changes (turn off for production)
These are simple, beginner-friendly HTML files—no fancy frameworks needed.
templates/login.html (User Login Form)
<!DOCTYPE html> <html> <head> <title>Topic Recommender Login</title> <style> body { font-family: Arial, sans-serif; max-width: 500px; margin: 2rem auto; padding: 0 1rem; } .form-group { margin-bottom: 1.2rem; } label { display: block; margin-bottom: 0.5rem; font-weight: bold; } input { width: 100%; padding: 0.6rem; border: 1px solid #ddd; border-radius: 4px; } button { padding: 0.7rem 1.5rem; background: #2563eb; color: white; border: none; border-radius: 4px; cursor: pointer; } .error-message { color: #dc2626; margin-bottom: 1rem; } </style> </head> <body> <h1>Welcome to Topic Recommender!</h1> {% if error %} <p class="error-message">{{ error }}</p> {% endif %} <form method="POST"> <div class="form-group"> <label for="flag">Filter Flag (Optional):</label> <input type="text" id="flag" name="flag" placeholder="e.g., sports_only, tech_only"> </div> <div class="form-group"> <label for="userId">User ID:</label> <input type="text" id="userId" name="userId" required placeholder="Enter your User ID (1-4 for sample data)"> </div> <button type="submit">Get My Recommendations</button> </form> </body> </html>
templates/recommendations.html (Recommendation Display)
<!DOCTYPE html> <html> <head> <title>Your Topic Recommendations</title> <style> body { font-family: Arial, sans-serif; max-width: 500px; margin: 2rem auto; padding: 0 1rem; } .recommendation-list { list-style: none; padding: 0; } .recommendation-list li { background: #f3f4f6; padding: 1rem; margin-bottom: 0.8rem; border-radius: 4px; } .back-link { margin-top: 1.5rem; display: inline-block; color: #2563eb; text-decoration: none; } </style> </head> <body> <h1>Hi User {{ user_id }}! Here’s What We Think You’ll Love:</h1> {% if recommendations %} <ul class="recommendation-list"> {% for topic in recommendations %} <li>✨ {{ topic }}</li> {% endfor %} </ul> {% else %} <p>Sorry, no recommendations are available for you right now.</p> {% endif %} <a href="/" class="back-link">← Go back to login</a> </body> </html>
- Place all your files in the project structure defined earlier
- Run the app with:
python app.py - Open your browser and go to
http://localhost:5000 - Enter a valid User ID (e.g., 1 from the sample data) and optionally a filter flag like
sports_only, then submit—you’ll see your personalized recommendations!
- Adjust the
interest_topic_mapinapp.pyto match your actual interest categories and topics - Modify the collaborative filtering logic (e.g., use item-based filtering instead of user-based, or adjust the number of similar users considered)
- Add more form validation (e.g., restrict flag inputs to allowed values)
- For larger datasets, replace CSV files with a local SQLite database (still compatible with Pandas)
内容的提问来源于stack exchange,提问作者Peachazoid

