[Python] [Word] [python-docx] Einfache Analyse von Diff-Daten mit Python

Sie können jetzt Dox mit Python-Docx in Last Post erstellen. Dieses Mal habe ich als Anwendung versucht, das Ergebnis von diff zu erhalten. Ich werde es auch mit der Bedeutung eines Memorandums entlarven. Ich hoffe, es ist hilfreich für diejenigen, die über die Verwaltung der Differenzinformationen von Dateien nachdenken.

Betriebsumgebung

Es ist ein System, das Cygwin einen Unterschied machen soll (lacht), also habe ich es in der folgenden Umgebung überprüft.

Für die Installation von Python-Docx usw. [hier im Artikel von 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) kann ebenfalls hilfreich sein.

Was tun mit diff

Die Verwendung von diff, diesmal die Zielanalyse, ist auf Folgendes beschränkt.

Grundsätzlich wird angenommen, dass es in "diff -r -u3 <Ziel 1> <Ziel 2>" verwendet wird. Ändern Sie einfach die Nummer nach u oder vergleichen Sie die Dateien allein anstelle von -r, und es sollte wahrscheinlich funktionieren. Wenn die Nachricht japanisch ist, müssen Sie sie vorübergehend als "export LANG = en_US" in Englisch ändern.

Wenn ich es tatsächlich mache, bekomme ich diesen Unterschied (dies ist ein Teil des openssl-Codes)

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

Basierend auf den Differenzinformationen in diesem Format werden wir diesmal die folgende einfache Analyse durchführen.

Verfassung

Dieses Mal habe ich die folgenden drei Python-Dateien vorbereitet und implementiert.

Von diesen wurde die Operation von Python-Docx bereits veröffentlicht, daher werde ich die verbleibenden zwei hier vorstellen.

Tatsächlicher Code

ParseDiff-Klasse, die Diff-Dateien analysiert

Der erste ist der Code für die De-facto-Hauptklasse ParseDiff, die die Diff-Datei analysiert.

#!/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 #Hier können Sie Anpassungen vornehmen, um keine Nachricht zu senden.

    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):
        #Wenn Sie die Daten der Textdatei unverändert hinzufügen, tritt ein Zeilenumbruch auf
        #Entfernen Sie es, da es ein Ärger sein wird
        text = text.replace("\n", "")
        text = text.replace("\r", "")
        return text

    def adjust_filetext(self, text):
        #Wenn Sie es in Word ausdrücken möchten, müssen Sie es Unicode machen, damit dieser Prozess.
        #Nur für CSV spielt die Codierung keine Rolle. Lassen Sie sie also unverändert.
        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):
        #Legen Sie die Anzahl der Differenzzeilen als Daten der Differenzinformationsliste fest
        #Die Anzahl der Differenzlinien wird nacheinander gezählt.
        #Wenn die Verarbeitung zur nächsten Datei wechselt oder wenn die gesamte Verarbeitung abgeschlossen ist
        #Rufen Sie hier an, um die Anzahl der Differenzleitungen zu bestimmen.
        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):
        #Gibt an, ob am Anfang des Textes eine Wortfolge steht
        if text.find(word) == 0:
            return True
        else:
            return False

    def diff_command(self, text):
        #Untersuchen Sie den Text, um festzustellen, ob der Text des Befehls diff am Anfang steht.
        #Gibt an, ob der Rückgabewert der Text des Befehls diff war
        #Der Text des Befehls diff wird ohne besondere Verarbeitung durchlaufen
        return self.check_word(text, "diff -r")

    def only_message(self, text):
        #Untersuchen Sie den Text, um festzustellen, ob Nur am Anfang steht.
        #Gibt an, ob der Rückgabewert als Nur verarbeitet wurde.

        #Die einzige Nachricht ist
        # Only in PATH: FILENAME
        #Aus der obigen Meldung PATH/Machen Sie nur FILENAME_Zur Liste hinzufügen
        ONLY_IN = "Only in "
        PATH_END = ": "
        if self.check_word(text, ONLY_IN) == False:
            return
        #Pfadzeichenfolge extrahieren
        start = len(ONLY_IN)
        end = text.find(PATH_END, start+1)
        if end < 0:
            return #Komm normalerweise nicht her
        path = text[start:end]
        #Fragen Sie nach dem Dateinamen
        start = end + 1
        filename = text[start:]
        filename = filename.replace("\n", "") #Zeilenumbrüche entfernen

        #nur zur Liste hinzufügen
        self.only_list.append(path + " " + filename)
        return True

    def filename_minus(self, text):
        #Untersuche den Text---Überprüfen Sie, ob es am Anfang ist.
        #Der Rückgabewert ist---Ob die Verarbeitung durchgeführt wurde oder nicht.

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

        #An erster Stelle---ob
        MINUS_TOP_MESSAGE = "--- "
        start = text.find(MINUS_TOP_MESSAGE)
        if start != 0:
            return False

        #Holen Sie sich die letzte Position des Pfadnamens (siehe Format oben)
        end = text.find("\t")
        if end < 0:
            return False

        #Weniger als,---Was tun, wenn ein Pfad gefunden wird?
        #Dies ist der Beginn der Verarbeitung für jede Datei.

        #Die Anzahl der Differenzzeilen in der vorherigen Datei wird hier bestätigt. Aktualisieren Sie sie daher.
        self.mark_diff_count()

        #Die Differenzdateiliste wurde hinzugefügt und die Dateinameninformationen beschrieben.
        name = text[len(MINUS_TOP_MESSAGE):end]
        list = [name, 0]
        self.file_list.append(list)
        if self.print_message:
            print "..." + name

        #Wenn docx nicht angegeben ist, wird keine Verarbeitung durchgeführt.
        if self.output_docxname == None:
            return True

        #Schreiben Sie diese Informationen in docx. Text ist farbig
        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):
        #Untersuche den Text+++Überprüfen Sie, ob es am Anfang ist.
        #Der Rückgabewert ist+++Ob die Verarbeitung durchgeführt wurde oder nicht.
        if self.check_word(text, "+++ ") == False:
            return False

        #Wenn docx nicht angegeben ist, wird keine Verarbeitung durchgeführt.
        if self.output_docxname == None:
            return True

        #Schreiben Sie in Farbe an docx.
        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):
        #Die Differenzinformationen werden hier verarbeitet.

        #Codierung der Verarbeitung, falls erforderlich, bis keine tatsächliche Situation vorliegt
        text = self.adjust_filetext(text)
        if len(text) == 0:
            return

        #Wenn es einen Unterschied gibt, Farbcode und Anzahl
        red = False
        blue = False
        if text[0] == "+":
            self.latect_diff_cnt += 1
            red = True
        elif text[0] == "-":
            blue = True
            self.latect_diff_cnt += 1

        #Wenn Sie docx nicht angeben, wird nur gezählt
        if self.output_docxname == None:
            return

        #Fügen Sie Text hinzu, wenn docx angegeben ist
        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):
        #Zeile für Zeile analysieren.
        if self.diff_command(text):
            return #Da die Beschreibung des Befehls diff nicht aufgezeichnet werden muss, ist sie abgeschlossen

        if self.only_message(text):
            return #nur Nachrichtenverarbeitung

        if self.filename_minus(text):
            # "--- path1"Verarbeitung im Zusammenhang mit der Beschreibung von
            return

        if self.filename_plus(text):
            # "+++ path1"Verarbeitung im Zusammenhang mit der Beschreibung von
            return

        #Schreiben Sie anders als oben als Differenzinformationen.
        self.do_diff_text(text)

    def make_cvs(self):
        #Setzen Sie die Informationen zur Differenzdatei auf csv.

        #Differenzinformationen schreiben
        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)

        #Nur Informationen, sortieren und dann zuerst schreiben.
        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):
        #Haupt der Diff-Analyse

        #Zeile für Zeile aus der Datei lesen und analysieren
        diff_fp = open(self.input_diffname, "r")
        while True:
            line = diff_fp.readline()
            if len(line) <= 0:
                break;
            self.parse_line(line)
        #Die Differenzinformationen der letzten Datei werden hier bestätigt. Aktualisieren Sie sie daher.
        self.mark_diff_count()
        diff_fp.close()

        #Speichern, wenn die docx-Ausgabe angegeben ist
        if self.output_docxname != None:
            self.docx.save(self.output_docxname)

        #Erstellen Sie eine CSV.
        self.make_cvs()

Entschuldigung für den schmutzigen Code wie gewohnt. Ich werde eine kurze Erklärung für diejenigen geben, die seltsam zu sehen sind.

Zunächst werden die Grundparameter mit init und set_docx_param festgelegt. Nachfolgend finden Sie eine kurze Beschreibung der Mitglieder der ParseDiff-Klasse.

Mitglied Inhalt
src_codename Zeichencode("shift-jis"Und)
input_diffname Der Pfad der Textdatei, die das unterschiedliche Ergebnis enthält
cvs_name CSV-Pfad ausgeben
file_list 1 Daten für Differenzinformationen, [Pfad] und [Anzahl der Differenzlinien]. Liste davon
only_list Eine Liste von Dateipfaden, die sich nur in dem einen oder anderen befinden
latect_diff_cnt Differenzanzahl der aktuell verarbeiteten Datei
output_docxname Wenn der Pfad des Ausgabe-Dox None ist, wird kein Dox erstellt
docx SimpleDocxService-Klasse

Die Anwendungsseite soll solchen Code schreiben.

Ich denke also, dass Sie den Ablauf verstehen können, wenn Sie ihn über die Analysefunktion betrachten (ich denke, dass der Code zu schmutzig und schwierig ist, aber Takisweat).

Anwendung

Es ist relativ einfach, da die Anwendungsseite nur Parse aufruft.

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

#
# diff --strip-trailing-cr -r -Analysieren Sie basierend auf dem Ergebnis von u3 Pfad1 Pfad2.
#

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,        #Dateiname
                "Courier New",      #Schriftartenname
                8,                  #Schriftgröße
                u"Differenzinformationen",         #Titel
                image               #Eröffnungsbild
            )
    diff.parse()

    print "complete."

Das Argument ist wie folgt gesetzt.

Der Zeichencode ist diesmal auf Shift-Jis festgelegt (es tut mir leid, da der Anwendungsfall in mir fast der von Winddows verwendete Quellcode war). Die hintere Bilddatei ist ebenfalls behoben. Wenn Sie diesen Teil dynamisch ändern möchten, gibt es meiner Meinung nach eine Lösung, z. B. das Hinzufügen zum Argument oder das Erstellen einer separaten Einstellungsdatei.

Eigentlich verwenden

Annahmen usw.

Die empfohlenen Bedingungen für die Ausführung des obigen Codes sind wie folgt.

Dieses Mal habe ich mich entschlossen, diese empfohlene Bedingung zu erfüllen, da ich einen Unterschied gemacht und den Quellcode unter Windows mit Cygwin analysiert habe. Der Dateiname kann natürlich durch Ändern der Importbeschreibung geändert werden. Sie müssen auch den Teil ersetzen, der in der folgenden Erklärung make_diff_report sagt.

Ich brauche auch eine Bilddatei. In diesem Artikel habe ich wie bei Letztes Mal die folgenden Bilder von professionellen Studenten verwendet.

report_top.png

Übrigens wird das Material eines professionellen Studenten aus dem Folgenden erhalten, und die Größe und die Zeicheneinfügung werden verarbeitet. http://pronama.azurewebsites.net/pronama/

Und natürlich gibt es auch eine Lizenz (http://pronama.azurewebsites.net/pronama/guideline/). Denken Sie also daran.

Wie benutzt man

Machen Sie zuerst die Differenzinformationen in eine entsprechende Textdatei auf Cygwin. Folgen Sie den unteren Schritten. Der Export ist nicht erforderlich, wenn die Nachricht in erster Linie auf Englisch ist. Sobald dies erledigt ist, ist sie danach nicht mehr erforderlich.


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

Wenn Sie dies tun, werden die Differenzinformationen in diff.txt enthalten. Schauen Sie also kurz mit dem Editor nach, ob es einen Unterschied gibt, wie oben beschrieben. Wenn es also die gewünschten Daten zu geben scheint, werde ich sie mit dieser Python analysieren.

Dieses Mal haben wir eine Methode zur Ausgabe von nur CSV und eine Methode zur Ausgabe von dox vorbereitet. Dies liegt daran, dass der doxx-Prozess Zeit benötigt, wenn der Unterschied groß ist. Wenn Sie nur statistische Daten wünschen, habe ich festgestellt, dass die Verarbeitung nur mit CSV schneller ist, also mache ich das.

Es wäre so, wenn nur CSV ausgestellt würde.

 python make_diff_report.py diff.txt diff.csv

Sie haben eine Datei namens diff.csv. Wenn Sie dies in Excel betrachten, werden statistische Daten wie folgt ausgegeben (ein wenig auf dem Excel-Bildschirm verarbeitet).

parse_diff_csv.JPG

Auf diese Weise sehen Sie eine Liste der Differenzdateien und deren Anzahl der Zeilen sowie eine Liste der Dateien, die nur eine davon sind.

Wenn Sie auch dox veröffentlichen möchten, gehen Sie wie folgt vor.

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

Neben diff.csv wird auch diff.docx generiert. Wenn es auf einer Station geöffnet wird, sieht es so aus.

parse_diff_docx.JPG

Ich konnte es analysieren. Übrigens verwende ich in meinem Fall CSV normalerweise nur zur Ausgabe statistischer Informationen, und einige Dateien werden von dox ausgegeben und später aus Wörtern verarbeitet.

Lizenz

Ich habe es unten benutzt. Vielen Dank für die Bereitstellung der wunderbaren Software.

das ist alles.

Recommended Posts

[Python] [Word] [python-docx] Einfache Analyse von Diff-Daten mit Python
Datenanalyse mit Python-Pandas
Empfehlung zur Datenanalyse mit MessagePack
Eine einfache Datenanalyse von Bitcoin, die von CoinMetrics in Python bereitgestellt wird
Datenanalyse Python
[Python] [Word] [python-docx] Versuchen Sie, mit python-docx eine Vorlage für einen Wortsatz in Python zu erstellen
Einführungsstudie zur Python-Ausgabe von Verkaufsdaten mit tapple-
Aufgezeichnete Umgebung für die Datenanalyse mit Python
Datenanalyse mit Python 2
Datenanalyse mit xarray
Datenanalyse Übersicht Python
Datenbereinigung mit Python
Python-Datenanalysevorlage
Datenanalyse mit Python
Erläuterung des Konzepts der Regressionsanalyse mit Python Teil 2
Berechnen Sie den Regressionskoeffizienten der einfachen Regressionsanalyse mit Python
Fordern Sie die Hauptkomponentenanalyse von Textdaten mit Python heraus
Liste des Python-Codes, der bei der Big-Data-Analyse verwendet wird
Erläuterung des Konzepts der Regressionsanalyse mit Python Teil 1
Erläuterung des Konzepts der Regressionsanalyse mit Python Extra 1
[Technisches Buch] Einführung in die Datenanalyse mit Python -1 Kapitel Einführung-
Zusammenfassung der statistischen Datenanalysemethoden mit Python, die im Geschäftsleben verwendet werden können
[In-Database Python Analysis Tutorial mit SQL Server 2017] Schritt 4: Feature-Extraktion von Daten mit T-SQL
Mein Python-Datenanalyse-Container
Python für die Datenanalyse Kapitel 4
Statische Analyse von Python-Programmen
[Python] Hinweise zur Datenanalyse
Python: Grundlagen der Verwendung von Scikit-Learn ①
# 1 [python3] Einfache Berechnung mit Variablen
Lernnotizen zur Python-Datenanalyse
Einfache FPS-Messung von Python
Python für die Datenanalyse Kapitel 2
Einfache Regressionsanalyse mit Python
Python für die Datenanalyse Kapitel 3
[Einführung] Künstliche Satellitendatenanalyse mit Python (Google Colab-Umgebung)
[Python] Ich habe versucht, Daten mit der API von Wikipedia zu sammeln
Ich habe 4 Bibliotheken des Python 3 Engineer Certification Data Analysis-Tests studiert
Bilderfassung von Firefox mit Python
Erste einfache Regressionsanalyse in Python
Datenerfassung mit Python Googlemap API
Python: Zeitreihenanalyse: Vorverarbeitung von Zeitreihendaten
Praktische Übung zur Datenanalyse mit Python ~ 2016 New Coder Survey Edition ~
Trübungsentfernung mit Python detailEnhanceFilter
Basiskarteninformationen mithilfe der Python-Geotiff-Konvertierung numerischer Höhendaten
Praxis der Datenanalyse durch Python und Pandas (Tokyo COVID-19 Data Edition)
Vorverarbeitungsvorlage für die Datenanalyse (Python)
Implementierung von Desktop-Benachrichtigungen mit Python
Zeitreihenanalyse 3 Vorverarbeitung von Zeitreihendaten
Datenanalyse beginnend mit Python (Datenvisualisierung 1)
Datenanalyse beginnend mit Python (Datenvisualisierung 2)
Datenverarbeitung 2 Analyse verschiedener Datenformate
Analysieren Sie die Mundpropaganda-Daten von Karriere-Change-Meetings mithilfe von Deep Learning emotional
Python-E-Book-Zusammenfassung nützlich für die frei lesbare Datenanalyse
Ich habe versucht, eine Clusteranalyse von Kunden anhand von Kaufdaten durchzuführen
Automatische Erfassung von Aktienkursen mit Python
Informationen zum Erstellen einer GUI mit TKinter of Python
Python-Visualisierungstool für die Datenanalyse
Übung, dies in Python zu verwenden (schlecht)
Maschinelles Lernen mit Python (2) Einfache Regressionsanalyse