[PYTHON] Ist es möglich, die Profilinformationen der Person aus dem Chat-Protokoll zu extrahieren?

Zweck

Umwelt und Daten

API zur Analyse

Da es nicht genug Wissen gibt, um es von Grund auf selbst zu analysieren, hat NTT Communications diesmal die [COTOHA API] veröffentlicht (https://api.ce-cotoha.com/contents/index.html). Wurde benutzt.

Originale Daten

Dieses Mal denke ich darüber nach, das Chat-Protokoll als Basis zu verwenden. Apropos Chat in Japan: LINE ist der Mainstream, aber LINE verfügt über eine Chat-Protokoll-Exportfunktion. Dieses Mal analysieren wir anhand des von LINE exportierten Chat-Protokolls. Für alle Fälle haben wir die vorherige Zustimmung der Person eingeholt.

Die Datei war zu groß

Normalerweise spreche ich nicht über langweilige Dinge, die die Profile des anderen nicht so sehr berühren, aber es war eine ziemlich große Datei. Beginnen wir mit der Formatierung dieser Datei.

Obwohl dies nicht der Fall ist, ist das Chat-Protokoll von LINE so aufgebaut.

Beispiel einer Originaldatei


2019/12/22 Sun
17:00 bowtin [Sticker]
17:01  hogehogekun [Sticker]
17:02 hogehogekun Lass uns Ramen essen, wenn wir heute Freizeit haben

2019/12/23 Mon
05:Es tut mir leid, dass ich geschlafen habe
05:00  bowtin [Sticker]
08:35 hogehogekun vergib nicht
   :
   :

Zunächst haben wir die folgenden Informationen entfernt:

Infolgedessen wurde es wie folgt.

Formatierte Datei


Wenn du heute frei bist, lass uns Ramen essen
unverzeihlich

Da es sich um eine Zeile pro Chat handelt, ist es visuell relativ einfach zu verstehen. Die Anzahl der Zeilen in der formatierten Datei betrug ungefähr 20500.

Teilen Sie die Datei in ca. 500 Zeilen

Zum Zeitpunkt der formatierten Datei war es ein ziemlich großes Chat-Protokoll mit 20500 Zeilen. Wenn ich die API so wie sie ist getroffen habe, ist ein Fehler zurückgekommen, und ich habe sie in Dateien mit jeweils etwa 500 Zeilen unterteilt. (Ich hätte glob benutzen sollen ...)

filesplitter.py



with open(file=r'\path\to\file\sample_chatlog.txt', mode='r', encoding='utf-8') as old_file:
    lines = old_file.readlines()

    for i in range(0, 21000, 500):
        line_count = 0 + i
        while line_count <= i + 500:
            with open(file=r'\path\to\file\splitted_file' + str(i) + '.txt', mode='a+', encoding='utf-8') as new_file:
                new_file.write(lines[line_count + i])
                line_count += 1

Ich denke, es gibt einen besseren Weg, es zu schreiben, aber vorerst bestand der Zweck darin, die Datei zu teilen, also werde ich dies verwenden.

Benutzerattributschätzung mithilfe der COTOHA-API

Die COTOHA-API verfügt über verschiedene öffentlich zugängliche APIs. Dieses Mal verwenden wir jedoch "Benutzerattributschätzung". Hat. Diese API befindet sich noch in der Beta-Phase (Stand: 19. Februar 2020).

Lassen Sie uns nun den gesamten Inhalt der ersten Datei an die API übergeben.

Geschätztes Ergebnis der ersten Datei


{"civilstatus": "Unverheiratet", "earnings": "1M-3M", "gender": "Weiblich", "hobby": ["INTERNET", "MUSIC", "PAINT", "TRAVEL", "TVGAME"], "moving": ["BUS", "WALKING"], "occupation": "Student"},

es ist wunderbar. Etwa 80% sind geeignet.

Ich werde fortsetzen.

{"civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["COOKING", "FORTUNE", "GOURMET", "INTERNET", "MUSIC", "TRAVEL"], "location": "Kanto", "moving": ["RAILWAY", "WALKING"]},

Diesmal habe ich ein etwas anderes Ergebnis erzielt. Was ist "Gewinn": "-1M"? Gibt es ein Minus im Jahreseinkommen? ?? Nachtrag: Ich habe einen Kommentar erhalten, der als "0-1M" anstelle von "-1M" interpretiert werden kann. Das könnte stimmen! Es bedeutet "weniger als 1 Million" oder "weniger als 1 Million".

Auch diesmal gab es Informationen über die Gegend. Die Informationen, die extrahiert werden können, scheinen sich je nach Originaldaten geringfügig zu unterscheiden.

Danach habe ich ungefähr 40 Dateien an die API übergeben. Da die obige Antwort gerade zurückgegeben wird, habe ich versucht, alle zurückgegebenen in einer Datei zu speichern.

Hier ist der Code, den ich tatsächlich verwendet habe.

main.py


#Grundlegende Informationen zu Anforderungen an die API
BASE_URL = 'https://api.ce-cotoha.com/hogehoge/'
CLIENT_ID = 'YOUR ID'
CLIENT_SECRET = 'YOUR SECRET'
TOKEN_SERVER_URL = 'https://api.ce-cotoha.com/hogehoge/'


#Eine Funktion, die ein API-Zugriffstoken erwirbt (ist es eine Spezifikation, dass das Zugriffstoken in regelmäßigen Abständen ungültig wird?...Es tut mir leid, wenn es anders ist)
def authorization():
    payload = {
        'grantType': 'client_credentials',
        'clientId': CLIENT_ID,
        'clientSecret': CLIENT_SECRET
    }
    headers = {
        'content-type': 'application/json'
    }
    response = requests.post(TOKEN_SERVER_URL, data=json.dumps(payload), headers=headers)
    auth_info = response.json()

    return auth_info['access_token']


#Eine Funktion, die eine Anforderung an die API stellt (Argument ist eine Liste von Zeichenfolgen).
def make_request(original_string_list):
    headers = {
        'Content-Type': 'application/json',
        'charset': 'UTF-8',
        'Authorization': 'Bearer ' + authorization()
    }

    payload = {
        'document': original_string_list,
        'type': 'kuzure' #Es scheint, dass es einen Modus dafür gibt, wenn Sätze wie Chat-Protokolle gebrochen sind
    }

    response = requests.post(BASE_URL, data=json.dumps(payload), headers=headers)

    jsonified_response = response.json()
    return jsonified_response['result']


if __name__ == '__main__':
    #Listen Sie die Dateinamen von ungefähr 40 Originaldateien auf (diesmal haben wir Regelmäßigkeit in Form von Dateiname + Nummer)
    file_list = ['splitted_file' + str(i) + '.txt' for i in range(0, 21000, 500)]

    #Holen Sie sich einen Dateinamen aus der Liste der Dateinamen und lesen Sie den Inhalt
    for a_file in file_list:
        lines = []
        with open(file=(r'path\to\file' + a_file), mode='r', encoding='utf-8') as file:
            lines = file.readlines()
            file.close()
        
        #Werfen Sie den gelesenen Inhalt unverändert in die COTOHA-API und speichern Sie das Ergebnis in einer Datei
        with open(file=r'path\to\file\result.txt', mode='a+', encoding='utf-8') as file:
            file.write(json.dumps(parse(lines)))
            file.close()
            sleep(1) #Wenn Sie in kurzer Zeit zu viele Anfragen stellen, kann dies zu Problemen führen. Warten Sie daher 1 Sekunde

Ergebnis

Deshalb einige Auszüge, aber die Liste der Ergebnisse sieht so aus. Auch im gleichen Alter gibt es einige Variationen.

Ergebnis der Benutzerattributextraktion (Teilauszug).py


[
{"age": "20-29 Jahre alt", "civilstatus": "Unverheiratet", "gender": "Weiblich", "hobby": ["COOKING", "FORTUNE", "INTERNET", "TVCOMMEDY"], "moving": ["OTHER", "WALKING"]},
{"age": "20-29 Jahre alt", "civilstatus": "Unverheiratet", "gender": "Weiblich", "hobby": ["GOURMET", "INTERNET", "SMARTPHONE_GAME", "PAINT", "TVGAME"], "moving": ["CYCLING", "OTHER", "RAILWAY", "WALKING"]},
{"civilstatus": "Unverheiratet", "earnings": "1M-3M", "gender": "Weiblich", "hobby": ["COOKING", "GOURMET", "INTERNET", "SHOPPING", "TRAVEL"], "moving": ["CYCLING"]},
{"age": "30-39 Jahre alt", "civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["ANIMAL", "CAMERA", "COLLECTION", "COOKING", "INTERNET", "SHOPPING"]},
{"age": "20-29 Jahre alt", "civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["COOKING", "FORTUNE", "GOURMET", "PAINT"], "location": "Tokai", "moving": ["RAILWAY"]},
{"age": "20-29 Jahre alt", "civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["ANIMAL", "DRAMA", "GYM", "SMARTPHONE_GAME", "MUSIC", "TVGAME"], "moving": ["RAILWAY", "WALKING"]}
]

Ich bin mir nicht sicher, ob dies der Fall ist, also möchte ich das zusammenfassen. Ich werde das obige Ergebnis als Python-Diktat hart codieren.

parse_result.py


results = [ 
  {"age": "20-29 Jahre alt", "civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["ANIMAL", "DRAMA", "GYM", "SMARTPHONE_GAME", "MUSIC", "TVGAME"], "moving": ["RAILWAY", "WALKING"]},
  {"age": "30-39 Jahre alt", "civilstatus": "Unverheiratet", "earnings": "-1M", "gender": "Weiblich", "hobby": ["ANIMAL", "CAMERA", "COLLECTION", "COOKING", "INTERNET", "SHOPPING"]}
  #Folgendes wird weggelassen
]


from collections import Counter
import itertools

#Sie können Sammlungen verwenden, um die häufigsten Werte abzurufen
print(Counter([data['age'] for data in dict_array if 'age' in data]).most_common()[0][0])
print(Counter([data['location'] for data in dict_array if 'location' in data]).most_common()[0][0])
print(Counter([data['gender'] for data in dict_array if 'gender' in data]).most_common()[0][0])
print(Counter([data['civilstatus'] for data in dict_array if 'civilstatus' in data]).most_common()[0][0])
print(Counter([data['earnings'] for data in dict_array if 'earnings' in data]).most_common()[0][0])

#Da die Liste eine Liste enthält, werfe ich einfach alles in eine flache Liste und rufe dann die häufigsten Werte ab.
print(Counter(list(itertools.chain.from_iterable([data['hobby'] for data in dict_array if 'hobby' in data]))).most_common()[0][0])

Die Zusammenfassung der häufigsten Werte ist wie folgt.

Häufigster Wert


20-29 Jahre alt
Kanto
Weiblich
Unverheiratet
1M-3M
INTERNET

Erwägung

Ich denke die Genauigkeit ist ziemlich hoch. Zumindest hätte ich in einem Chat mit dieser Person nicht darüber sprechen sollen, ob ich verheiratet bin, und natürlich habe ich nicht die einfache Frage gestellt: "Bist du eine Frau?" Die Geschichte des Jahreseinkommens kann ein wenig sein.

Übrigens habe ich ein wenig versucht, während ich mit anderen Leuten plauderte, aber es war größtenteils richtig.

In Zukunft können Sie möglicherweise das wahre Profil der Person aus dem Chat-Protokoll in gewissem Umfang mit einer passenden App usw. herausfinden! In Anbetracht der Abweichungen scheinen Menschen, die normalerweise unterschiedliche Zeichen verwenden, herauszufinden, dass sie diese richtig verwenden.

Zusammenfassend stellte sich heraus, dass Leute ihr Profil im Chat unerwartet verschüttet haben, aber ich denke, dass es für diejenigen, die gründlich in der Charaktererstellung sind, wie VTuber und das sogenannte Nekama, schwer zu verstehen ist.

Recommended Posts

Ist es möglich, die Profilinformationen der Person aus dem Chat-Protokoll zu extrahieren?
[Dance Dance Revolution] Ist es möglich, den Schwierigkeitsgrad (Fuß) aus dem Wert des Groove-Radars vorherzusagen?
Wählen Sie PDFMiner, um Textinformationen aus PDF zu extrahieren
Löschen Sie das cron.log regelmäßig, um ein Wachstum zu verhindern.
Senden Sie Protokolldaten vom Server an Splunk Cloud
Fügen wir es der Umgebungsvariablen mit dem Befehl ~ hinzu
Ist es möglich, ähnliche Bilder nur mit ImageHash zu erkennen?
Melden Sie sich von Selenium aus beim Fortigate (6.0) -Verwaltungsbildschirm an, um sich abzumelden
Sie, die das Protokoll ausmalen, um es besser sehen zu können
So melden Sie sich automatisch wie 1Password von der CLI an
Extrahieren Sie den Wert, der einem Wert am nächsten kommt, aus einem Listenelement in Python
So aktivieren Sie die Verbindung von außerhalb (außer localhost) mit dev_appserver.py von GAE / Py
Wie einfach ist es, ein Medikament auf dem Markt zu synthetisieren?
So extrahieren Sie die gewünschte Zeichenfolge aus einem Befehl in Zeile 4
Finden Sie alle Muster, um eine bestimmte Zahl aus dem Satz zu extrahieren