Analyser et visualiser JSON (application Web ⑤ avec Python + Flask)

Cliquez ici pour un aperçu de nos efforts.

  1. Préparation de l'environnement (configuration du système d'exploitation)
  2. Préparation de l'environnement (configuration sous OS)
  3. Tracez le contenu du QuickStart de Flask (installation et configuration minimale)
  4. Tracez le contenu de Flask's Tutrial (apprendre à créer une application de base)
  5. Créez un contenu original ★

La dernière fois a terminé jusqu'à 4. Je vais donc faire l'original, qui est le but initial. .. Ce que nous créons est une application qui lit un fichier JSON qui suppose une configuration spécifique et visualise le contenu. Certains produits peuvent générer des fichiers de configuration en JSON pour le travail, il serait donc pratique que je puisse les visualiser (éventuellement dans la sortie Excel). Je sens que ça existe même si je n'y arrive pas, mais je vais le faire comme une pratique.

Exigences

--Dispose d'un mécanisme pour télécharger des fichiers JSON --Parse le fichier JSON téléchargé et visualiser (une partie de) le contenu

Créons une application qui répond à cette exigence. En fait, il est plus facile d'imaginer utiliser le fichier json que vous souhaitez réellement utiliser, mais comme il contient des informations qui ne peuvent pas être diffusées en dehors de l'entreprise, utilisez plutôt celui publié sur Internet. http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/gettingstartedguide/samples/moviedata.zip Un fichier JSON qui enregistre les titres de films, les classements, les genres, etc.

Vérifiez le contenu du fichier JSON

Même si vous voulez le visualiser, vous devez d'abord comprendre de quel type de structure il s'agit (je pense ...). Je ne sais pas ce que feront les professionnels, mais en tant qu'amateur, j'utilise cette extension Chrome. http://jsoneditoronline.org/

20170309_004.jpg

Il y a un guimon qui se demande si cela convient à la visualisation, mais il y a une volonté de le rendre plus semblable à Excel, ou enfin d'Excel.

image

L'exemple JSON est un fichier qui résume les informations sur le film. Je voudrais en faire une image de la sortie suivante.

Title Rating Genre Actors
Prisoners 8.2 Crime Hugh Jackman
Drama Jake Gyllenhaal
Thriller Viola Davis

Le nombre de genre et d'acteurs est variable.

environnement

Comme environnement, utilisez la même VM que celle utilisée jusqu'à Dernière fois et divisez uniquement l'environnement virtuel Python (virtualenv).

installer

Structure du répertoire

Utilisez la structure de répertoires suivante.

Je vais omettre la partie qui est presque la même que la dernière fois.

Créer virtualenv

réduction

Créer un fichier de configuration

Cette fois, la partie qui définit la variable est séparée dans un autre fichier.

config.py


# -*- coding: utf-8 -*-

# configuration
DATABASE = '/root/jsonparser/db/jsonparser.db'
DEBUG = True
UPLOAD_FOLDER = '/root/jsonparser/uploads/'
ALLOWED_EXTENSIONS = set(['json'])
SECRET_KEY = 'development key'

Les variables définies ici sont accessibles à partir du fichier py qui a importé ce fichier par la procédure suivante.

  1. Créez une instance de Flask app = Flask(name)
  2. Lire les variables du fichier app.config.from_pyfile('config.py')
  3. Affectez le contenu de la variable UPLOAD_FOLDER à la variable temp temp = app.config['UPLOAD_FOLDER']

Créer une base de données pour stocker les informations sur les fichiers

Créez l'instruction SQL suivante et appelez-la depuis app.py comme précédemment pour initialiser la base de données. Le processus d'initialisation de app.py à ce stade est le même que la dernière fois, il est donc omis.

schema.sql


drop table if exists file_entries;
create table file_entries (
  id integer primary key autoincrement,
  filename string not null,
  desc string,
  created string
);

Création du corps principal

Afficher la fonction

Ajoutez la fonction suivante à app.py. Une fonction qui vérifie l'extension des fichiers téléchargés.

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config[
               'ALLOWED_EXTENSIONS']

Ensuite, la fonction de téléchargement des fichiers et la fonction de suppression (entrée) du fichier téléchargé.

@app.route('/', methods=['GET', 'POST'])
def inputfile():
    cur = g.db.execute(
        'select filename,desc,created,id from file_entries order by created desc')
    entries = [dict(filename=row[0], desc=row[1], created=row[
                    2], id=row[3]) for row in cur.fetchall()]

    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(url_for('inputfile'))
        file = request.files['file']
        # if user does not select file, browser also
        # submit a empty part without filename
        if file.filename == '':
            flash('No selected file')
            return redirect(url_for('inputfile'))
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            current = datetime.now()
            g.db.execute('insert into file_entries (filename,desc,created) values (?, ?, ?)',
                         [file.filename, request.form['desc'], current])
            g.db.commit()
            message = "File upload finished successfully."
            return redirect(url_for('inputfile', message=message))

    current = datetime.now().strftime('%Y/%m/%d %H:%M')
    message = request.args.get('message', '')
    if not message:
        message = "Current time is " + current
    return render_template('inputfile.html', message=message, entries=entries)
@app.route('/delete', methods=['GET', 'POST'])
def delete():
    id = request.args.get('value')
    g.db.execute("delete from file_entries where id = ?", [id])
    g.db.commit()
    return redirect(url_for('inputfile'))

Création HTML

Le modèle original

layout.html


<!doctype html>
<html>
<head>
  <title>JSON Parser</title>
  <script type="text/javascript" src="../static/js/jquery-3.1.1.min.js"></script>
  <link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
  {% block head %}{% endblock %}
</head>
<div class=page>
  <h1>JSON Parser</h1>
  <div class=metanav>
    <a href="{{ url_for('inputfile') }}">Home</a>
  </div>
  {% for message in get_flashed_messages() %}
    <div class=flash>{{ message }}</div>
  {% endfor %}
  {% block body %}{% endblock %}
</div>
</html>

Écran de téléchargement, de liste et de suppression de fichiers.

inputfile.html


{% extends "layout.html" %}
{% block body %}
  <p>{{ message }} </p>
  <form action="{{ url_for('inputfile') }}" method=post class=add-entry enctype="multipart/form-data">
    File:     <input type="file" name="file" size="30"/><br>
    Description: <input type="text" name="desc" size="30" placeholder="Description"/><br>
    <input type="submit" />
  </form>

  <ul class=entries>
  {% for entry in entries %}
    <li><h2>{{ entry.filename }}</h2>
    <p><a href="{{url_for('delete',value=entry.id)}}">Effacer</a></p>
        Description:   {{ entry.desc }}<br>
        Created:    {{ entry.created }}<br>
  {% else %}
    <li><em>Il n'y a pas encore d'entrées.</em>
  {% endfor %}
  </ul>
{% endblock %}

Téléchargez le fichier à partir de l'action de l'élément de formulaire. Utilisez url_for pour accéder à la fonction inputfile (URL correspondante) dans app.py.

Création CSS

La feuille de style est omise car elle utilise celle du didacticiel telle quelle.

Résultats à ce jour

Lorsque vous arrivez à ce stade, démarrez l'application et accédez-y depuis le navigateur,

[root@cnenarnupgd1c jsonparser]# . env/bin/activate
(env) [root@cnenarnupgd1c jsonparser]#
(env) [root@cnenarnupgd1c jsonparser]# python app.py
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 173-472-212

20170309_002.jpg

Lorsque vous téléchargez le fichier, 20170309_007.jpg

Jusqu'à ce point, c'est OK.

Perspective, affichage

Le kick sera l'écran qui affiche la liste des fichiers téléchargés créés précédemment. Ajoutez un lien appelé «Configurer la confirmation» à l'écran et passez-le à la fonction appelée sortie avec le nom du fichier cible.

inputfile.html(partie)


  <ul class=entries>
  {% for entry in entries %}
    <li><h2>{{ entry.filename }}</h2>
    <p><a href="{{url_for('output',value=entry.filename)}}">Vérification de la configuration</a></p>
    <p><a href="{{url_for('delete',value=entry.id)}}">Effacer</a></p>
	Description:   {{ entry.desc }}<br>
	Created:    {{ entry.created }}<br>
  {% else %}
    <li><em>Il n'y a pas encore d'entrées.</em>
  {% endfor %}
  </ul>

La fonction reçue est la suivante. En fonction du nom de fichier passé comme valeur, lisez le fichier json, transmettez-le au module pour analyse et transmettez l'objet renvoyé au modèle.

app.py(partie)


from parse_json import parse_json

@app.route('/output')
def output():
    fname = request.args.get('value').replace(' ','_')
    fpath = app.config['UPLOAD_FOLDER'] + fname
    jsonfile = open(fpath,'r')
    config = json.load(jsonfile)
    output = parse_json(config)

    return render_template('output.html', entries=output)

Vient ensuite le module d'analyse.

parse_json.py


import sys

def parse_json(config):
    # Initialize array
    # Create (num of movie) * empty {}
    arr = []
    for i in range(len(config)):
        try:
            arr[i].append({})
        except IndexError:
            arr.append({})
        except:
            print 'Unexpected Error:',sys.exc_info()[0]

    # Populate arr
    for idx,movie in enumerate(config):
        try:
            arr[idx].update({'title': movie.get('title')})
            arr[idx].update({'rank': movie.get('info').get('rank')})
            arr[idx].update({'genres': movie.get('info').get('genres')})
            arr[idx].update({'actors': movie.get('info').get('actors')})

            if movie.get('info').get('genres') and movie.get('info').get('actors'):
                arr[idx].update({'rowspan': max(len(movie.get('info').get('genres')),len(movie.get('info').get('actors')))})
            elif not movie.get('info').get('genres') and movie.get('info').get('actors'):
                arr[idx].update({'rowspan': len(movie.get('info').get('actors'))})
            elif movie.get('info').get('genres') and not movie.get('info').get('actors'):
                arr[idx].update({'rowspan': len(movie.get('info').get('genres'))})
            else:
                arr[idx].update({'rowspan': 1})
        except:
            print 'Unexpected Error:', sys.exc_info()[0]
            pass

    return arr

Pour être honnête, je pense qu'il est possible de traiter avec du code Flask (sur HTML) à ce niveau, mais je vais y réfléchir plus tard et le faire de cette façon. De plus, une variable appelée rowspan est calculée en cours de route, mais il s'agit d'une variable qui indique le nombre de lignes nécessaires pour chaque film.

Cliquez ici pour un modèle pour passer l'objet généré.

output.html


{% extends "layout.html" %} 
<h1>Movies</h1>
{% block body %}
  <table ~~~ style="table-layout:fixed;width:100%;" border = "3">
    <colgroup>
      <col style="width:25%;">
      <col style="width:25%;">
      <col style="width:25%;">
      <col style="width:25%;">
    </colgroup>
    <tr bgcolor="skyblue">
    <td ~~~ style="word-wrap:break-word;">Title</td>
    <td ~~~ style="word-wrap:break-word;">Rank</td>
    <td ~~~ style="word-wrap:break-word;">Genres</td>
    <td ~~~ style="word-wrap:break-word;">Actors</td>
    </tr>
  {% for entry in entries %}
    {% for i in range(entry.rowspan) %}
    <tr>
      {% if i == 0 %}
      <td ~~~ style="word-wrap:break-word;" rowspan = "{{ entry.rowspan }}">{{ entry.title }}</td>
      <td ~~~ style="word-wrap:break-word;" rowspan = "{{ entry.rowspan }}">{{ entry.rank }}</td>
      {% endif %}
      
      {% if entry.genres[i] %}
      <td ~~~ style="word-wrap:break-word;">{{ entry.genres[i] }}</td>
      {% else %}
      <td ~~~ style="word-wrap:break-word;" bgcolor="black">Empty</td>
      {% endif %}

      {% if entry.actors[i] %}
      <td ~~~ style="word-wrap:break-word;">{{ entry.actors[i] }}</td>
      {% else %}
      <td ~~~ style="word-wrap:break-word;" bgcolor="black">Empty</td>
      {% endif %}      
    </tr>
    {% endfor %}
  {% else %}
    <tr><td ~~~ style="word-wrap:break-word;" columnspan="4">No entry here.</td></tr>
  {% endfor %}
  </table>
{% endblock %}

Pour les entrées qui nécessitent 4 lignes, affichez le titre et le classement ensemble sur 4 lignes. Remplissez les cellules restantes.

En outre, la largeur de cellule est fixe afin que les chaînes de caractères longues soient enveloppées. Il fait référence à ce qui suit. http://qiita.com/n_s_y_m/items/cb29d730e63772b02475

résultat

La sortie sera la suivante. Quel que soit le nombre d'éléments, il est proche de l'image. 20170310_003.jpg

En fait, ce serait bien de pouvoir trier par colonne, mais une fois que cela est fait. La source entière, etc. est publiée ci-dessous. https://github.com/KI1208/jsonparser.git

Supplément, mémorandum

À première vue, il y a beaucoup de problèmes et de demandes à l'heure actuelle, mais je vais fermer les yeux et en faire un prochain numéro.

Recommended Posts

Analyser et visualiser JSON (application Web ⑤ avec Python + Flask)
Application Web avec Python + Flask ② ③
Application Web avec Python + Flask ④
Lancer un serveur Web avec Python et Flask
Développement d'applications Web avec Flask
Cours de production d'applications Web appris avec Flask of Python Partie 2 Chapitre 1 ~ Échange JSON ~
Encodage et décodage JSON avec python
Développement d'applications avec Docker + Python + Flask
POSTER diversement avec Python et recevoir avec Flask
Lire et écrire des fichiers JSON avec Python
[Python] Une application web rapide avec Bottle!
Application Web facile avec Python + Flask + Heroku
Exécutez une application Web Python avec Docker
Pratiquer le web scraping avec Python et Selenium
Scraping Web facile avec Python et Ruby
[GCP] Procédure de création d'une application Web avec Cloud Functions (Python + Flask)
Je souhaite créer une application Web en utilisant React et Python flask
[Python] Visualisez et identifiez les pièces lentes avec pytest
Lire JSON avec Python et générer un CSV
Gagnez l'application Web Python + Flask avec Jenkins
[Python3] Lecture et écriture avec isoformat datetime avec json
[Python] Utiliser JSON avec Python
Programmation avec Python Flask
Apprentissage automatique facile avec scikit-learn et flask ✕ Application Web
Essayez le fonctionnement de la base de données avec Python et visualisez avec d3
Visualisez la gamme d'insertions internes et externes avec python
Lancer une application Web Python sur Nginx + Gunicorn avec Docker
Application Web réalisée avec Python3.4 + Django (Construction de l'environnement Part.1)
Lire le fichier json avec Python, le formater et générer le json
POSTER l'image avec json et la recevoir avec flask
Hobby Web Engineer développe une application Web avec Vue.js + Flask (& GCP)
Création d'une application Web qui mappe les informations sur les événements informatiques avec Vue et Flask
Programmation avec Python et Tkinter
Chiffrement et déchiffrement avec Python
Web scraping avec python + JupyterLab
Python et matériel - Utilisation de RS232C avec Python -
Installez Python et Flask (Windows 10)
POST json avec le script Python 3
Créer une application Web avec Django
API Web avec Python + Falcon
python avec pyenv et venv
Formater json avec Vim (avec python)
Web scraping débutant avec python
Rationalisez la recherche Web avec Python
Fonctionne avec Python et R
Lire des données json avec python
Notes et manuels de référence lors de la création de services Web avec Flask
Écrivez facilement des conversions de classes de données JSON et Python avec quicktype et dacite
Application Web Python x Flask x Tensorflow.Keras qui prédit les races de chats 2
J'ai créé une application de livre simple avec python + Flask ~ Introduction ~
Exploration Web, scraping Web, acquisition de caractères et sauvegarde d'image avec python
Application Web avec Python3.3.1 + Bottle (1) - Changer le moteur de modèle en jinja2
Exemple d'analyse HTTP GET et JSON avec Pepper Python
Communiquez avec FX-5204PS avec Python et PyUSB
Briller la vie avec Python et OpenCV
La première intelligence artificielle. Testez la sortie Web avec python. ~ Introduction du flacon
Installez Python 2.7.9 et Python 3.4.x avec pip.
Bases de SNS Python faites avec Flask
Faisons une application WEB pour l'annuaire téléphonique avec flacon Partie 1