I provided the mandatory code below like flask app, predictionmodel.py and html code still I don't know what the problem is. whenever I run on localhost after clicking submit, I am getting error

The browser (or proxy) sent a request that this server could not understand.

Flask Application Server

from flask import Flask, jsonify, request, render_template
from predictionModel import PredictionModel
import pandas as pd
from random import randrange

app = Flask(__name__, static_folder="./static",
            template_folder="./templates")

@app.route("/")
def home():
    return render_template('index.html')


@app.route('/predict', methods=['POST'])
def predict():
    
    data = request.json  
    model = PredictionModel(data)  
    result = model.predict()  
    return jsonify(result)

if __name__ == '__main__':
    app.run()

Prediction Model Code

import timeit
from nltk.stem import WordNetLemmatizer
from nltk import pos_tag
from nltk.corpus import stopwords
from nltk.corpus import wordnet
import pickle as pickle
import pickle 
import string
import nltk
nltk.data.path.append('./nltk_data')

start = timeit.default_timer()


with open("pipeline.pkl", 'rb') as f:
            pipeline = pickle.load(f)
            stop = timeit.default_timer()
            print('=> Pickle Loaded in: ', stop - start)

       
class PredictionModel:
    output = {}

    
    def __init__(self, text):
        self.output['original'] = text

    def predict(self):

        self.preprocess()
        self.pos_tag_words()

        clean_and_pos_tagged_text = self.output['preprocessed'] + \
            ' ' + self.output['pos_tagged']

        self.output['prediction'] = 'FAKE' if pipeline.predict(
            [clean_and_pos_tagged_text])[0] == 0 else 'REAL'

        return self.output

    def preprocess(self):
        text = self.output['original'].lower()

        text = [t for t in text.split(" ") if len(t) > 1]

        text = [word for word in text if not any(c.isdigit() for c in word)]

        text = [word.strip(string.punctuation) for word in text]

        
        stop = stopwords.words('english')
        text = [x for x in text if x not in stop]

        text = [t for t in text if len(t) > 0]

        pos_tags = pos_tag(text)

        
        text = [WordNetLemmatizer().lemmatize(t[0], self.get_wordnet_pos(t[1]))
                for t in pos_tags]

        self.output['preprocessed'] = " ".join(text)

    def get_wordnet_pos(self, pos_tag):
        if pos_tag.startswith('J'):
            return wordnet.ADJ
        elif pos_tag.startswith('V'):
            return wordnet.VERB
        elif pos_tag.startswith('N'):
            return wordnet.NOUN
        elif pos_tag.startswith('R'):
            return wordnet.ADV
        else:
            return wordnet.NOUN

    def pos_tag_words(self):
        pos_text = nltk.pos_tag(
            nltk.word_tokenize(self.output['preprocessed']))
        self.output['pos_tagged'] = " ".join(
            [pos + "-" + word for word, pos in pos_text])

And following is the HTML code

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <link href="https://unpkg.com/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <title>Hello, world!</title>
  </head>
  <body>
    <header class="text-gray-600 body-font -my-10">
        <div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center">
          <a class="flex title-font font-medium items-center text-gray-900 mb-4 md:mb-0">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="w-10 h-10 text-white p-2 bg-purple-500 rounded-full" viewBox="0 0 24 24">
              <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"></path>
            </svg>
            <span class="ml-3 text-xl">Fake News Detection</span>
          </a>
          <nav class="md:ml-auto flex flex-wrap items-center text-base justify-center">
            <a class="mr-5 hover:text-gray-900">Home</a>
            <a class="mr-5 hover:text-gray-900">Contact us</a>
            <a class="mr-5 hover:text-gray-900">About us</a>
            
          </nav>
          
        </div>
      </header><hr>
      <section class="text-gray-600 body-font">
        <div class="container px-5 py-24 mx-auto">
          <div class="flex flex-col text-center w-full mb-20">
            <h2 class="text-xs text-indigo-500 tracking-widest font-medium title-font mb-1">MACHINE LEARNING PROJECT</h2>
            <h1 class="sm:text-3xl text-2xl font-medium title-font mb-4 text-gray-900">Fake News Detection</h1>
            <p class="lg:w-2/3 mx-auto leading-relaxed text-base">It is an easy tool to detect whether your input news is real or fake.</p>
          </div>
        <div class="center">
            <form action="/predict" method="POST">
                <div class="form-group">
                  <label for="exampleInputEmail1">Enter News</label>
                  <input type="text" class="form-control" id="news" name="news"  aria-describedby="emailHelp" placeholder="Enter news">
                  <small id="emailHelp" class="form-text text-muted">Thankyou for using our product</small>
                </div>
                <button type="submit" class="btn btn-primary">Submit</button>
              </form>
        </div> 
          
          
        </div>
      </section>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html
1

There are 1 best solutions below

0
Zain Ul Abidin On

The problem is in your predict route you defined in the Flask application.

@app.route('/predict', methods=['POST'])
def predict():
    
    data = request.json # Problem is here
    model = PredictionModel(data)  
    result = model.predict()  
    return jsonify(result)

The main problem is you are getting data by using request.json which is only valid if you are posting a valid json .e.g your app will work if i post the news like below

import requests

url = 'http://localhost:5000/predict'
headers = {'Content-Type': 'application/json'}
data = { "news": "Candice patton finally exposed her very important assets" }

response = requests.post(url, headers=headers, json=data)

print(response.status_code)

Notice the Content Type as application/json, but when you post the same thing from your html code the Content Type is text/html which flask parses in to the form attribute so to fix the error you need to change "request.data" to "request.form['news']" e.g. your update post endpoint would be

@app.route('/predict', methods=['POST'])
def predict():

    data = request.form['news']
    model = PredictionModel(data)  
    result = model.predict()  
    return jsonify(result)