You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django框架中实现HTML表单与Python MBTI分析脚本的对接

实现方案

步骤1:重构原有MBTI分析脚本,封装为可调用模块

首先移除原脚本的全局执行逻辑,封装为独立可调用函数,同时优化不必要的本地文件写入逻辑,避免多请求冲突。将重构后的文件命名为mbti_analyzer.py,放到你的Django应用根目录下,代码如下:

#  -*- coding: utf-8 -*-
import csv
import os
import pickle
import re
import string
from collections import Counter

import pandas as pd
import tweepy
from nltk.corpus import stopwords
from nltk.stem import *
from nltk.stem.snowball import SnowballStemmer
from nltk.tokenize import word_tokenize
from sklearn.feature_extraction.text import TfidfVectorizer
from unidecode import unidecode
from django.conf import settings

# 全局初始化资源,仅启动时加载一次,避免重复加载损耗性能
# 初始化Twitter API
ckey = settings.TWITTER_CKEY
csecret = settings.TWITTER_CSECRET
atoken = settings.TWITTER_ATOKEN
asecret = settings.TWITTER_ASECRET
auth = tweepy.OAuthHandler(ckey, csecret)
auth.set_access_token(atoken, asecret)
api = tweepy.API(auth)

# 加载词表
freq_path = os.path.join(settings.BASE_DIR, '你的应用名称', 'newfrequency300.csv')
with open(freq_path, 'rt') as f:
    csvReader = csv.reader(f)
    mydict = {rows[1]: int(rows[0]) for rows in csvReader}
vectorizer = TfidfVectorizer(vocabulary=mydict, min_df=1)

# 加载模型
model_IE = pickle.load(open(os.path.join(settings.BASE_DIR, '你的应用名称', "BNIEFinal.sav"), 'rb'))
model_SN = pickle.load(open(os.path.join(settings.BASE_DIR, '你的应用名称', "BNSNFinal.sav"), 'rb'))
model_TF = pickle.load(open(os.path.join(settings.BASE_DIR, '你的应用名称', 'BNTFFinal.sav'), 'rb'))
model_PJ = pickle.load(open(os.path.join(settings.BASE_DIR, '你的应用名称', 'BNPJFinal.sav'), 'rb'))

# 原有预处理逻辑保留
emoticons_str = r"""
    (?:
        [:=;] # Eyes
        [oO\-]? # Nose (optional)
        [D\)\]\(\]/\\OpP] # Mouth
    )"""

emoji_pattern = re.compile("["
                           u"\U0001F600-\U0001F64F"  # emoticons
                           u"\U0001F300-\U0001F5FF"  # symbols & pictographs
                           u"\U0001F680-\U0001F6FF"  # transport & map symbols
                           u"\U0001F1E0-\U0001F1FF"  # flags (iOS)
                           "]+", flags=re.UNICODE)

regex_str = [
    emoticons_str,
    r'<[^>]+>',  # HTML tags
    r'(?:@[\w_]+)',  # @-mentions
    r"(?:\#+[\w_]+[\w\'_\-]*[\w_]+)",  # hash-tags
    r'http[s]?://(?:[a-z]|[0-9]|[$-_@.&amp;+]|[!*\(\),]|(?:%[0-9a-f][0-9a-f]))+',  # URLs
    r'(?:(?:\d+,?)+(?:\.?\d+)?)',  # numbers
    r"(?:[a-z][a-z'\-_]+[a-z])",  # words with - and '
    r'(?:[\w_]+)',  # other words
    r'(?:\S)'  # anything else
]

tokens_re = re.compile(r'(' + '|'.join(regex_str) + ')', re.VERBOSE | re.IGNORECASE)
emoticon_re = re.compile(r'^' + emoticons_str + '$', re.VERBOSE | re.IGNORECASE)


def tokenize(s):
    return tokens_re.findall(s)


def preprocess(s, lowercase=False):
    tokens = tokenize(s)
    if lowercase:
        tokens = [token if emoticon_re.search(token) else token.lower() for token in tokens]
    return tokens


def preproc(s):
    s = unidecode(s)
    POSTagger = preprocess(s)
    tweet = ' '.join(POSTagger)
    stop_words = set(stopwords.words('english'))
    filtered_sentence = []
    for w in POSTagger:
        if w not in stop_words:
            filtered_sentence.append(w)
    stemmed_sentence = []
    stemmer2 = SnowballStemmer("english", ignore_stopwords=True)
    for w in filtered_sentence:
        stemmed_sentence.append(stemmer2.stem(w))
    temp = ' '.join(c for c in stemmed_sentence if c not in string.punctuation)
    preProcessed = temp.split(" ")
    final = []
    for i in preProcessed:
        if i not in final:
            if i.isdigit():
                pass
            else:
                if 'http' not in i:
                    final.append(i)
    temp1 = ' '.join(c for c in final)
    return temp1


def get_tweet_list(user):
    tweet_list = []
    try:
        for i in range(0, 4):
            tweets = api.user_timeline(screen_name=user, count=1000, include_rts=True, page=i)
            for status in tweets:
                tw = preproc(status.text)
                if tw.find(" ") == -1:
                    tw = "blank"
                tweet_list.append(tw)
        return tweet_list, None
    except tweepy.TweepError as e:
        return None, "账号不存在、账号私有或Twitter接口请求失败,请检查输入后重试"

# 核心分析逻辑封装为函数
def get_mbti(username):
    tweet_list, err = get_tweet_list(username)
    if err:
        return None, err
    x = vectorizer.fit_transform(tweet_list).toarray()
    df = pd.DataFrame(x)
    answer = []
    IE = model_IE.predict(df)
    SN = model_SN.predict(df)
    TF = model_TF.predict(df)
    PJ = model_PJ.predict(df)

    b = Counter(IE)
    value = b.most_common(1)
    if value[0][0] == 1.0:
        answer.append("I")
    else:
        answer.append("E")

    b = Counter(SN)
    value = b.most_common(1)
    if value[0][0] == 1.0:
        answer.append("S")
    else:
        answer.append("N")

    b = Counter(TF)
    value = b.most_common(1)
    if value[0][0] == 1:
        answer.append("T")
    else:
        answer.append("F")

    b = Counter(PJ)
    value = b.most_common(1)
    if value[0][0] == 1:
        answer.append("P")
    else:
        answer.append("J")
    mbti = "".join(answer)
    return mbti, None

步骤2:Django端功能实现

2.1 配置基础参数

在Django项目的settings.py中新增Twitter API配置,避免硬编码密钥:

# settings.py末尾添加
TWITTER_CKEY = '你的ckey'
TWITTER_CSECRET = '你的csecret'
TWITTER_ATOKEN = '你的atoken'
TWITTER_ASECRET = '你的asecret'

同时把原脚本依赖的newfrequency300.csv、4个.sav模型文件放到Django应用的根目录下。

2.2 编写表单类

在应用的forms.py中新增表单,用于校验用户输入的Twitter账号:

from django import forms

class TwitterHandleForm(forms.Form):
    username = forms.CharField(label='Twitter账号Handle', max_length=100, required=True, widget=forms.TextInput(attrs={'placeholder': '例如:elonmusk'}))

2.3 编写视图逻辑

在应用的views.py中编写请求处理逻辑,对接表单和分析模块:

from django.shortcuts import render
from .forms import TwitterHandleForm
from .mbti_analyzer import get_mbti

def mbti_analyze(request):
    mbti_result = None
    error_msg = None
    if request.method == 'POST':
        form = TwitterHandleForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            mbti_result, error_msg = get_mbti(username)
    else:
        form = TwitterHandleForm()
    return render(request, '你的原有HTML模板路径.html', {
        'form': form,
        'mbti_result': mbti_result,
        'error_msg': error_msg
    })

记得在应用的urls.py中新增对应路由绑定该视图。

2.4 修改HTML模板

在原有HTML页面中新增表单提交和结果展示区域:

<!-- 表单区域 -->
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">开始分析</button>
</form>

<!-- 结果展示区域 -->
{% if error_msg %}
<p style="color: red;">{{ error_msg }}</p>
{% endif %}
{% if mbti_result %}
<div style="margin-top: 20px; padding: 10px; border: 1px solid #eee;">
    <h3>分析结果:{{ mbti_result }}</h3>
</div>
{% endif %}

注意事项

  • 若分析耗时较长,建议在前端添加加载动画,避免用户重复提交表单
  • 可根据需求扩展MBTI对应性格描述的展示逻辑
  • 生产环境建议将Twitter API密钥通过环境变量注入,不要直接写在配置文件中

内容的提问来源于stack exchange,提问作者Shahzaib Sarwar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 07:54:04