[Python] [Word] [python-docx] Analyse simple des données de diff en utilisant python

Vous pouvez maintenant créer dox en utilisant python-docx dans Last Post. Cette fois, comme application de ceci, j'ai essayé d'obtenir le résultat de diff. Je vais également l'exposer au sens d'un mémorandum. J'espère que cela sera utile pour ceux qui pensent à gérer les informations de différence des fichiers.

Environnement d'exploitation

C'est un système qui est censé prendre une différence sur Cygwin (rires), donc je l'ai vérifié dans l'environnement suivant.

Pour l'installation de python-docx, etc., [ici dans l'article sur python_docx](http://qiita.com/GDaigo/items/d5b46fc43c6250dd61b1#python-docx%E3%81%AE%E3%82%A4%E3%83% B3% E3% 82% B9% E3% 83% 88% E3% 83% BC% E3% 83% AB) peuvent également être utiles.

Que faire avec diff

L'utilisation de diff, qui est l'analyse cible cette fois, est limitée à ce qui suit.

Fondamentalement, il est supposé être utilisé dans "diff -r -u3 <cible 1> <cible 2>". Changez simplement le nombre après u, ou comparez les fichiers seuls au lieu de -r et cela devrait probablement fonctionner. De plus, si le message est en japonais, il doit être temporairement en anglais sous la forme "export LANG = en_US".

Quand je le fais réellement, j'obtiens cette différence (cela fait partie du code openssl)

diff -r -u3 async_old/arch/async_win.c async_new/arch/async_win.c
--- async_old/arch/async_win.c	2017-07-07 08:19:02.000000000 +0900
+++ async_new/arch/async_win.c	2017-07-09 22:58:36.556937300 +0900
@@ -47,7 +47,12 @@
     return 1;
 }
 
-VOID CALLBACK async_start_func_win(PVOID unused)
+VOID CALLBACK async_start_func_win2(PVOID unused)
+{
+    async_start_func();
+}
+
+VOID CALLBACK async_start_func_win3(PVOID unused)
 {
     async_start_func();
 }
 
 Only in async_new/: tst.c

Sur la base des informations de différence dans ce format, nous effectuerons cette fois l'analyse simple suivante.

Constitution

Cette fois, j'ai préparé et implémenté les trois fichiers python suivants.

Parmi ceux-ci, le fonctionnement de python-docx a déjà été publié, je vais donc présenter les deux autres ici.

Code réel

ParseDiff classe qui analyse les fichiers diff

Le premier est le code de la classe ParseDiff principale de facto qui analyse le fichier diff.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from docx_simple_service import SimpleDocxService

class ParseDiff:

    def __init__(self, src_codename, diff_name, cvs_name):
        self.FILE_LIST_PATH_INDEX = 0
        self.FILE_LIST_COUNT_INDEX = 1
        self.src_codename = src_codename
        self.input_diffname = diff_name
        self.cvs_name = cvs_name
        self.file_list = []
        self.only_list = []
        self.latect_diff_cnt = 0
        self.docx = None
        self.output_docxname = None
        self.print_message = True #Vous pouvez faire des ajustements ici pour ne pas envoyer de message.

    def set_docx_param(self, docx_name, font_name, font_size, title, title_img):
        self.output_docxname = docx_name
        self.docx = SimpleDocxService()
        self.docx.set_normal_font(font_name, font_size)
        self.docx.add_head(title, 0)
        if title_img != None:
            self.docx.add_picture(title_img, 3.0)

    def adjust_return_code(self, text):
        #Si vous ajoutez les données du fichier texte telles quelles, un saut de ligne se produira
        #Retirez-le car ce sera un problème
        text = text.replace("\n", "")
        text = text.replace("\r", "")
        return text

    def adjust_filetext(self, text):
        #Si vous voulez le mettre en mots, vous devez le rendre unicode, donc ce processus.
        #Pour csv uniquement, l'encodage n'a pas vraiment d'importance, alors laissez-le tel quel.
        if self.output_docxname != None:
            text = self.docx.get_unicode_text(text, self.src_codename)
        text = self.adjust_return_code(text)
        return text

    def mark_diff_count(self):
        #Définissez le nombre de lignes de différence comme données de la liste d'informations de différence
        #Le nombre de lignes de différence est compté séquentiellement.
        #Lorsque le traitement passe au fichier suivant ou lorsque tout le traitement est terminé
        #Appelez ici pour déterminer le nombre de lignes différentielles.
        index = len(self.file_list) - 1
        if index >= 0:
            self.file_list[index][self.FILE_LIST_COUNT_INDEX] = self.latect_diff_cnt
        self.latect_diff_cnt = 0

    def check_word(self, text, word):
        #S'il existe une chaîne de mots depuis le début du texte
        if text.find(word) == 0:
            return True
        else:
            return False

    def diff_command(self, text):
        #Examinez le texte pour voir si le texte de la commande diff est au début.
        #Si la valeur de retour était le texte de la commande diff
        #Le texte de la commande diff est passé sans traitement spécial
        return self.check_word(text, "diff -r")

    def only_message(self, text):
        #Examinez le texte pour voir si Only est au début.
        #Si la valeur de retour a été traitée comme Only.

        #Le seul message est
        # Only in PATH: FILENAME
        #À partir du message ci-dessus PATH/Créer FILENAME uniquement_Ajouter à la liste
        ONLY_IN = "Only in "
        PATH_END = ": "
        if self.check_word(text, ONLY_IN) == False:
            return
        #Extraire la chaîne de chemin
        start = len(ONLY_IN)
        end = text.find(PATH_END, start+1)
        if end < 0:
            return #Habituellement, ne viens pas ici
        path = text[start:end]
        #Demander le nom du fichier
        start = end + 1
        filename = text[start:]
        filename = filename.replace("\n", "") #Supprimer les sauts de ligne

        #ajouter seulement à la liste
        self.only_list.append(path + " " + filename)
        return True

    def filename_minus(self, text):
        #Examiner le texte---Vérifiez si c'est au début.
        #La valeur de retour est---Que le traitement ait été effectué ou non.

        # ---Exemple de format
        # --- async_old/async_err.c¥t017-07-07 08:19:02.000000000 +0900

        #En premier lieu---qu'il s'agisse
        MINUS_TOP_MESSAGE = "--- "
        start = text.find(MINUS_TOP_MESSAGE)
        if start != 0:
            return False

        #Obtenez la dernière position du nom du chemin (voir format ci-dessus)
        end = text.find("\t")
        if end < 0:
            return False

        #Moins que,---Que faire si un chemin est trouvé.
        #C'est le début du traitement de chaque fichier.

        #Le nombre de lignes différentielles dans le fichier précédent sera confirmé ici, alors mettez-le à jour.
        self.mark_diff_count()

        #Ajout de la liste des fichiers de différence et description des informations de nom de fichier.
        name = text[len(MINUS_TOP_MESSAGE):end]
        list = [name, 0]
        self.file_list.append(list)
        if self.print_message:
            print "..." + name

        #Si docx n'est pas spécifié, aucun traitement n'est effectué.
        if self.output_docxname == None:
            return True

        #Écrivez ces informations dans docx. Le texte est coloré
        self.docx.add_head(u"――――――――――――――――――――――――――――――――――", 1)
        self.docx.open_text();
        text = self.adjust_filetext(text)
        self.docx.add_text_color(text, 0,0,255)
        self.docx.close_text();

        return True

    def filename_plus(self, text):
        #Examiner le texte+++Vérifiez si c'est au début.
        #La valeur de retour est+++Que le traitement ait été effectué ou non.
        if self.check_word(text, "+++ ") == False:
            return False

        #Si docx n'est pas spécifié, aucun traitement n'est effectué.
        if self.output_docxname == None:
            return True

        #Écrivez dans docx en couleur.
        self.docx.open_text();
        text = self.adjust_filetext(text)
        self.docx.add_text_color(text, 255,0,0)
        self.docx.close_text();
        return True

    def do_diff_text(self, text):
        #Les informations de différence sont traitées ici.

        #Traitement d'encodage si nécessaire, en cas d'absence de situation réelle
        text = self.adjust_filetext(text)
        if len(text) == 0:
            return

        #S'il y a une différence, code couleur et compte
        red = False
        blue = False
        if text[0] == "+":
            self.latect_diff_cnt += 1
            red = True
        elif text[0] == "-":
            blue = True
            self.latect_diff_cnt += 1

        #Si docx n'est pas spécifié, il ne fait que compter, c'est donc la fin
        if self.output_docxname == None:
            return

        #Ajouter du texte si docx est spécifié
        self.docx.open_text();
        if red:
            self.docx.add_text_color(text, 255,0,0)
        elif blue:
            self.docx.add_text_color(text, 0,0,255)
        else:
            self.docx.add_text(text)
        self.docx.close_text();

    def parse_line(self, text):
        #Analysez ligne par ligne.
        if self.diff_command(text):
            return #La description de la commande diff n'étant pas soumise à enregistrement, elle est

        if self.only_message(text):
            return #uniquement Traitement des messages

        if self.filename_minus(text):
            # "--- path1"Traitement lié à la description de
            return

        if self.filename_plus(text):
            # "+++ path1"Traitement lié à la description de
            return

        #Autre que ce qui précède, écrivez comme informations de différence.
        self.do_diff_text(text)

    def make_cvs(self):
        #Définissez les informations du fichier de différence sur csv.

        #Écriture des informations de différence
        cvs_fp = open(self.cvs_name, "w")
        cvs_fp.write(u"diff path, lines, \r\n")
        for file_obj in self.file_list:
            if self.print_message:
                print "flle:" , file_obj
            cvs_text =  file_obj[self.FILE_LIST_PATH_INDEX] + "," + \
                        str(file_obj[self.FILE_LIST_COUNT_INDEX]) + ",\r\n"
            cvs_fp.write(cvs_text)

        #Seules les informations, triez puis écrivez d'abord.
        self.only_list.sort()
        cvs_fp.write(u"only path,\r\n")
        for only in self.only_list:
            if self.print_message:
                print "only:" , only
            cvs_fp.write(only + ",\r\n")
        cvs_fp.close();

    def parse(self):
        #Principale de l'analyse des différences

        #Lire ligne par ligne du fichier et analyser
        diff_fp = open(self.input_diffname, "r")
        while True:
            line = diff_fp.readline()
            if len(line) <= 0:
                break;
            self.parse_line(line)
        #Les informations de différence du dernier fichier seront confirmées ici, alors mettez-les à jour.
        self.mark_diff_count()
        diff_fp.close()

        #Enregistrer si la sortie docx est spécifiée
        if self.output_docxname != None:
            self.docx.save(self.output_docxname)

        #Créez un CSV.
        self.make_cvs()

Désolé pour le code sale comme d'habitude. Je vais donner une brève explication à ceux qui sont étranges à voir.

Tout d'abord, les paramètres de base sont définis avec init et set_docx_param. Vous trouverez ci-dessous une brève spécification des membres de la classe ParseDiff.

membre Contenu
src_codename Code de caractère("shift-jis"Et)
input_diffname Le chemin du fichier texte contenant le résultat différent
cvs_name Chemin CSV de sortie
file_list 1 données pour les informations de différence, [chemin] et [nombre de lignes de différence]. Liste de ceci
only_list Une liste de chemins de fichiers qui ne se trouvent que dans l'un ou l'autre
latect_diff_cnt Nombre de différences du fichier en cours de traitement
output_docxname Si le chemin du dox de sortie est None, dox ne sera pas créé
docx Classe SimpleDocxService

Le côté application est censé écrire un tel code.

Donc, je pense que vous pouvez comprendre le flux si vous le regardez depuis la fonction d'analyse (je pense que le code est trop sale et c'est difficile, mais Takisweat)

application

C'est relativement facile car le côté application appelle simplement parse.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# diff --strip-trailing-cr -r -Analyse basée sur le résultat de u3 path1 path2.
#

import sys
#from docx_simple_service import SimpleDoxService
from parse_diff import ParseDiff

if __name__ == "__main__":

    if len(sys.argv) < 3:
        print "You need docx. ->    parse_diff.py diff_name csv_name docx_name"
        print "You need csv only -> parse_diff.py diff_name csv_name"
        sys.exit(1)

    docx_name = None
    if len(sys.argv) > 3:
        docx_name = sys.argv[3]

    diff = ParseDiff("shift-jis", sys.argv[1], sys.argv[2])
    image = "report_top.png "
    diff.set_docx_param(
                docx_name,        #nom de fichier
                "Courier New",      #Nom de la police
                8,                  #taille de police
                u"Informations sur la différence",         #Titre
                image               #Photo d'ouverture
            )
    diff.parse()

    print "complete."

L'argument est défini comme suit.

Le code de caractère est fixé à shift-jis cette fois (je suis désolé car le cas d'utilisation en moi était presque le code source utilisé par Winddows). Le fichier image arrière est également fixe. Si vous souhaitez modifier cette partie de manière dynamique, je pense qu'il existe une solution telle que l'ajouter à l'argument ou créer un fichier de paramètres séparé.

En fait utiliser

Hypothèses, etc.

Les conditions recommandées pour exécuter le code ci-dessus sont les suivantes.

Cette fois, j'ai fait cette condition recommandée en raison de mes circonstances de prendre un diff et d'analyser le code source sur Windows avec Cygwin. Le nom du fichier peut être changé, bien sûr, en modifiant la description de l'importation. Vous devez également remplacer la partie qui dit make_diff_report dans l'explication suivante.

J'ai également besoin d'un fichier image. Dans cet article, comme pour Dernière fois, j'ai utilisé les images suivantes d'étudiants professionnels.

report_top.png

À propos, le matériel d'étudiant professionnel est obtenu à partir de ce qui suit, et la taille et l'insertion de caractères sont traitées. http://pronama.azurewebsites.net/pronama/

Et, bien sûr, il existe également une Licence, alors gardez à l'esprit.

Comment utiliser

Tout d'abord, faites les informations de différence dans un fichier texte approprié sur Cygwin. Suivez les étapes ci-dessous. L'exportation n'est pas nécessaire si le message est en anglais en premier lieu, et une fois terminé, il n'est plus nécessaire par la suite.


export LANG=en_US
diff -r -u3 Dossier cible 1 Dossier cible 2> diff.txt

Si vous le faites, les informations de différence seront incluses dans diff.txt, alors jetez un coup d'œil rapide avec l'éditeur et voyez s'il y a une différence comme décrit ci-dessus. Donc, s'il semble y avoir les données souhaitées, je vais les analyser avec ce python.

Cette fois, nous avons préparé une méthode pour sortir uniquement CSV et une méthode pour sortir dox. En effet, le processus doxx prend du temps lorsque la différence est importante. Si vous voulez juste des données statistiques, j'ai trouvé qu'il est plus rapide de traiter uniquement avec csv, donc je le fais.

Ce serait comme ça si seulement CSV était émis.

 python make_diff_report.py diff.txt diff.csv

Vous aurez un fichier appelé diff.csv. Si vous regardez cela dans Excel, les données statistiques sortiront comme ceci (un peu traitées sur l'écran Excel)

parse_diff_csv.JPG

De cette façon, vous verrez une liste de fichiers de différence et leur nombre de lignes, et une liste de fichiers qui ne sont que l'un d'entre eux.

Ensuite, si vous souhaitez également publier dox, procédez comme suit.

 python make_diff_report.py diff.txt diff.csv diff.docx

En plus de diff.csv, diff.docx est également généré. Lorsqu'il est ouvert dans une salle, cela ressemble à ceci.

parse_diff_docx.JPG

J'ai pu l'analyser. À propos, dans mon cas, j'utilise généralement CSV uniquement pour générer des informations statistiques, et certains fichiers sont générés par dox, puis traités à partir de mots.

Licence

Je l'ai utilisé ci-dessous. Merci d'avoir fourni le merveilleux logiciel.

c'est tout.

Recommended Posts

[Python] [Word] [python-docx] Analyse simple des données de diff en utilisant python
Analyse de données à l'aide de pandas python
Recommandation d'analyse des données à l'aide de MessagePack
Une analyse simple des données de Bitcoin fournie par CoinMetrics en Python
Analyse de données python
[Python] [Word] [python-docx] Essayez de créer un modèle de phrase de mot en Python en utilisant python-docx
Étude introductive sur Python-Sortie des données de vente à l'aide de tapple-
Environnement enregistré pour l'analyse des données avec Python
Analyse de données avec python 2
Analyse des données à l'aide de xarray
Présentation de l'analyse de données python
Nettoyage des données à l'aide de Python
Modèle d'analyse de données Python
Analyse de données avec Python
Explication du concept d'analyse de régression à l'aide de python Partie 2
Calculer le coefficient de régression d'une analyse de régression simple avec python
Défiez l'analyse des composants principaux des données textuelles avec Python
Liste du code Python utilisé dans l'analyse de Big Data
Explication du concept d'analyse de régression à l'aide de Python Partie 1
Explication du concept d'analyse de régression à l'aide de Python Extra 1
[Livre technique] Introduction à l'analyse de données avec Python -1 Chapitre Introduction-
Résumé des méthodes d'analyse de données statistiques utilisant Python qui peuvent être utilisées en entreprise
[Didacticiel d'analyse Python dans la base de données avec SQL Server 2017] Étape 4: Extraction de fonctionnalités de données à l'aide de T-SQL
Mon conteneur d'analyse de données python
Python pour l'analyse des données Chapitre 4
Analyse statique des programmes Python
[Python] Notes sur l'analyse des données
python: principes de base de l'utilisation de scikit-learn ①
# 1 [python3] Calcul simple à l'aide de variables
Notes d'apprentissage sur l'analyse des données Python
Mesure FPS simple de python
Python pour l'analyse des données Chapitre 2
Analyse de régression simple avec Python
Python pour l'analyse des données Chapitre 3
[Introduction] Analyse de données satellitaires artificielles à l'aide de Python (environnement Google Colab)
[Python] J'ai essayé de collecter des données en utilisant l'API de wikipedia
J'ai étudié 4 bibliothèques de test d'analyse de données de certification d'ingénieur Python 3
Capture d'image de Firefox en utilisant Python
Première analyse de régression simple en Python
Acquisition de données à l'aide de l'API googlemap de python
Python: analyse des séries chronologiques: prétraitement des données des séries chronologiques
Exercice pratique d'analyse de données avec Python ~ 2016 New Coder Survey Edition ~
Suppression de la brume à l'aide de Python detailEnhanceFilter
Informations sur la carte de base à l'aide de la conversion Geotiff Python des données numériques d'élévation
Pratique de l'analyse de données par Python et pandas (Tokyo COVID-19 data edition)
Modèle de prétraitement pour l'analyse des données (Python)
Implémentation des notifications de bureau à l'aide de Python
Analyse des séries chronologiques 3 Prétraitement des données des séries chronologiques
Analyse de données à partir de python (visualisation de données 1)
Analyse de données à partir de python (visualisation de données 2)
Traitement des données 2 Analyse de divers formats de données
Analyser émotionnellement les données de bouche-à-oreille d'entreprise des réunions de changement de carrière à l'aide de l'apprentissage en profondeur
Résumé du livre électronique Python utile pour l'analyse de données gratuite
J'ai essayé d'effectuer une analyse de cluster de clients à l'aide des données d'achat
Collecte automatique des cours boursiers à l'aide de python
À propos de la création de l'interface graphique à l'aide de TKinter de Python
Outil de visualisation Python pour le travail d'analyse de données
Pratique d'utilisation de ceci en Python (mauvais)
Apprentissage automatique avec python (2) Analyse de régression simple