[JAVA] Ich habe versucht, eine Webanwendung zu erstellen, die Tweets mit einer Vue-Word-Cloud durchsucht und die Tendenz untersucht, was im zugehörigen Profil geschrieben steht

Es ist das, was Sie oft sehen.

Ich werde Ihnen das Ergebnis zuerst für diejenigen zeigen, die sagen, was es ist.

図1.PNG

Wenn Sie nach einem Tweet nach einem Suchwort suchen, wird das Wort des Profils der Person, die den Treffer getwittert hat, in der Tag-Cloud von Word Cloud angezeigt.

Zeichen, die häufig angezeigt werden, sind größer.

Es scheint einfach zu machen, aber wenn ich es nachschlage, ist es meistens Python.

Im Moment entwickle ich mit Vue.js und Java (Spring Boot), also dachte ich, ich könnte es damit schaffen, also habe ich eine kleine Webanwendung erstellt.

Diesmal ist es nicht der Inhalt des Tweets, aber der Inhalt des Profils wird aus dem Inhalt des Tweets gezogen, so dass dies möglicherweise etwas schwierig ist.

Tage für die Erstellung von Webanwendungen: 2 Tage Qiita Artikelerstellung: 2 Tage

Die Erstellung von Qiita-Artikeln ist schwieriger.

Warum endete der Titel so lange?

Der Betriebsablauf der Webanwendung ist wie folgt.


Holen Sie sich Profilinformationen von Tweets mit der Twitter-API ↓ Morphologische Analyse von Profilinformationen ↓ Visualisierung
Was ist morphologische Analyse?

Es fühlt sich an, als würde man einen Satz in Wörter aufteilen, aber ich weiß nicht viel mehr, also bin ich sicher, dass Sie damit besser vertraut sind.

2. Umwelt

Vue.js:2.6.12 Spring Boot:v2.3.3 Java:AdoptOpenJDK:11.0.6 Kuromoji:0.9.0 vue-wordcloud:1.1.1 axios:0.20.0

Vue.js ist die Front und Spring Boot ist die serverseitige API ohne jegliche Disziplin.

Die grobe Verzeichnisstruktur sieht so aus.

┠ src
┃  ┗ main
┃     ┗ java/app/myapp
┃        ┠ common
┃        ┃  ┗ HttpAccess.java
┃        ┠ controller
┃        ┃  ┗ TwitterAnalysisRestController.java
┃        ┠ entity
┃        ┃  ┗ VueWordCloudEntity.java
┃        ┠ service
┃        ┃  ┗ TwitterAnalysisService.java
┃ Verschiedene
┃
┠ web
┃ ┠ Verschiedene
┃  ┠ src
┃ ┃ ┠ Verschiedene
┃  ┃  ┠ router
┃ ┃  ┃  ┗ index.js
┃  ┃  ┠ views
┃  ┃  ┃  ┗ TwitterAnalysis.vue
┃  ┃  ┃
┃ ┃ Verschiedene
┃ Verschiedene
┃
┠ build.gradle
verschiedene

3. Vorgehensweise

3-1. Voraussetzung

Ein Spring Boot-Projekt wurde erstellt.

3-2. Twitter API-Verwendungsanwendung

Zunächst müssen Sie die Verwendung der Twitter-API auf der Twitter-Seite beantragen.

Es wird davon ausgegangen, dass Sie einen Twitter-Account haben.

Es gibt eine Website, die freundlicherweise erklärt wird. Bitte beachten Sie dies, wenn Sie sich für die Verwendung bewerben. Detaillierte Erklärung vom Beispielsatz der Twitter-API-Verwendungsanwendung der Version 2020 bis zum Erwerb des API-Schlüssels

Die Informationen ändern sich von Tag zu Tag, sodass sie sich möglicherweise geändert haben, aber wahrscheinlich einfacher sein sollten.

Alles was Sie tun müssen, ist ein paar Fragen von der Twitter-Seite zu beantworten.

Auf jeden Fall ist der Anwendungsbildschirm gezwungen, auf Englisch zu schreiben, aber tatsächlich kann es auf Japanisch sein ...

Als ich die Frage beantwortete, dachte ich, ich warte auf die Genehmigung ... aber das war nicht der Fall, und ich konnte sofort zum Anzeigebildschirm Token (Bearer Token) wechseln.

Alles was Sie tun müssen, ist dieses Token und den Schlüssel zu kopieren.

Es scheint, dass es vor einiger Zeit mehrere Tage gedauert hat, bis die Genehmigung vorliegt.

3-3. Java-Implementierung

Holen Sie sich zunächst Profilinformationen über die Twitter-API.

Es scheint praktisch, eine Bibliothek namens Twitter4J zu verwenden, aber ich habe sie diesmal nicht verwendet.

Es gibt keinen besonderen Grund.

Die API-URL sieht folgendermaßen aus.

Es scheint, dass die API kürzlich aktualisiert wurde.

https://api.twitter.com/2/tweets/search/recent?expansions=author_id&user.fields=description&max_results=100&query=<Suchbegriff>
Diesmal verwendete Parameter Inhalt
expansions=author_id Bezeichnet, um Informationen über die Person zu erhalten, die den Tweet gleichzeitig mit dem Text des Tweets erstellt hat
user.fields=description Gibt an, dass der Profiltext der Person, die getwittert hat, in die zu erfassenden Informationen aufgenommen wird
max_results=100 Maximale Anzahl von Akquisitionen
query= ツイートに対するSuchbegriff

Weitere Informationen finden Sie unter Offizielle Website.

Das Abrufen von Informationen mithilfe der API ist also wie folgt.

Geben Sie für das Token das oben erhaltene Inhaber-Token an.

TwitterAnalysisService.java


String urlString = "https://api.twitter.com/2/tweets/search/recent?expansions=author_id&user.fields=description&max_results=100";

String method = "GET";
String bearerToken = <Zeichen>;

HttpAccess httpAccess = new HttpAccess();
String response = httpAccess.requestHttp(urlString, method, bearerToken, <Suchbegriff>);

HttpAccess.java


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class HttpAccess {

    public String requestHttp(String urlString, String method, String bearerToken, String query) {

        String result = null;
        String urlStringFull = null;

        if (query == null || query.isEmpty()) return result;

        try {
            urlStringFull = urlString + "&query=" + URLEncoder.encode(query, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        if (urlStringFull == null) return result;
        
        HttpURLConnection  urlConn = null;
        InputStream in = null;
        BufferedReader reader = null;

        try {

            URL url = new URL(urlStringFull);

            urlConn = (HttpURLConnection) url.openConnection();
            urlConn.setRequestMethod(method);
            urlConn.setRequestProperty("Authorization","Bearer " + bearerToken);
            urlConn.connect();

            int status = urlConn.getResponseCode();
            if (status == HttpURLConnection.HTTP_OK) {

                in = urlConn.getInputStream();
                    
                reader = new BufferedReader(new InputStreamReader(in));
                
                StringBuilder output = new StringBuilder();
                String line;
                
                while ((line = reader.readLine()) != null) {
                    output.append(line);
                }

                result = output.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
				if (urlConn != null) {
					urlConn.disconnect();
				}
			} catch (IOException e) {
                e.printStackTrace();
			}
        }
        
        return result;
    }
}

Als nächstes folgt die morphologische Analyse. Wenn Sie dies in Java tun möchten, ist Kuromoji praktisch.

Fügen Sie einfach eine Zeile zur Datei build.gradle hinzu.

build.gradle


dependencies {
~ Abkürzung ~
    implementation 'com.atilika.kuromoji:kuromoji-ipadic:0.9.0'
~ Abkürzung ~
}

Was das Format für die Rückgabe der Daten betrifft, werden "Name" und "Wert" als Schlüssel verwendet, da vue-wordcloud das Array von Objekten mit "Name" und "Wert" als Schlüssel in der Ansicht behandelt. Gibt ein Array von Objekten in JSON zurück.

Geben Sie das Wort als Ergebnis der morphologischen Analyse in "Name" ein und geben Sie an, wie oft das Wort in "Wert" vorkommt.

Dieses Mal wurde zusätzlich zum Zugriff auf die obige API eine morphologische Analyse durchgeführt, um ein Objekt mit "Name" und "Wert" in den folgenden Feldern zu erstellen.

Verwenden Sie die Tokenizer-Klasse für die morphologische Analyse.

TwitterAnalysisService.java


import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.atilika.kuromoji.ipadic.Token;
import com.atilika.kuromoji.ipadic.Tokenizer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import app.myapp.common.HttpAccess;
import app.myapp.entity.VueWordCloudEntity;

@Service
public class TwitterAnalysisService {

    public List<VueWordCloudEntity> analysisTwitterProfileByQuery(String query) {

        List<VueWordCloudEntity> result = new ArrayList<>();

        String urlString = "https://api.twitter.com/2/tweets/search/recent?expansions=author_id&user.fields=description&max_results=100";

        String method = "GET";
        String bearerToken = <Zeichen>;

        HttpAccess httpAccess = new HttpAccess();
        String response = httpAccess.requestHttp(urlString, method, bearerToken, query);

        if (response == null) return result;

        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = null;

        try {
            root = mapper.readTree(response);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        if (root == null || root.get("meta").get("result_count").asInt() == 0) {
            return result;
        }

        Tokenizer tokenizer = new Tokenizer();
        List<Token> tokens = new ArrayList<>();

        JsonNode users = root.get("includes").get("users");

        for(int i = 0; i < users.size(); i++) {
            if (users.get(i).get("description") != null) {
                tokens.addAll(tokenizer.tokenize(users.get(i).get("description").asText()));
            }
        }

        List<VueWordCloudEntity> vueWordCloudEntityList = new ArrayList<>();
        tokens.stream()
                .filter(x -> x.getPartOfSpeechLevel1().equals("Substantiv"))
                .map(x -> x.getSurface())
                .collect(Collectors.groupingBy(x -> x, Collectors.counting()))
                .forEach((k, v) -> {
                    VueWordCloudEntity vueWordCloudEntity = new VueWordCloudEntity();
                    vueWordCloudEntity.setName(k);
                    vueWordCloudEntity.setValue(v);
                    vueWordCloudEntityList.add(vueWordCloudEntity);
                });

        result = vueWordCloudEntityList;
            
        return result;
    }
}

VueWordCloudEntity.java


import lombok.Data;

@Data
public class VueWordCloudEntity {

    private String name;
    private Long value;
}

TwitterAnalysisRestController.java


import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import app.myapp.entity.VueWordCloudEntity;
import app.myapp.service.TwitterAnalysisService;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class TwitterAnalysisRestController {

    @Autowired
    private TwitterAnalysisService twitterAnalysisService;

    @GetMapping("/twitter/analysis/profile/by/{query}")
    public ResponseEntity<List<VueWordCloudEntity>> analysisTwitterProfileByQuery(
            @PathVariable String query) {

        List<VueWordCloudEntity> result
                = twitterAnalysisService.analysisTwitterProfileByQuery(query);

        //CORS kompatibel hier für Test-App
        HttpHeaders headers = new HttpHeaders();
        headers.add("Access-Control-Allow-Credentials", "true");
        headers.add("Access-Control-Allow-Origin", "http://localhost:<Vue.js Ausführungsumgebung Portnummer>");

        return new ResponseEntity<>(result, headers, HttpStatus.OK);
    }
}

Ich bin sicher, es gibt einen einfacheren Weg, wenn Sie Twitter4J nicht in Java verwenden!

Ich bin sicher, dass es irgendwo eine solche Probe gibt.

Leider war es diesmal meine Probe.

3-4. Implementierung von Vue.js

Dies ist einfach, da Sie einfach vue-wordcloud installieren und die offizielle vue-wordcloud-Quelle kopieren und einfügen.

Erstellen Sie ein Projekt mit der Benutzeroberfläche von vue-cli und platzieren Sie es an der Position der obigen Verzeichnisstruktur.

Installieren Sie dann die vue-word cloud mit der vue-cli-GUI.

Oh, und Axios auch.

Kopieren Sie anschließend das offizielle Beispiel und fügen Sie es ein, korrigieren Sie es ein wenig und rufen Sie die Daten von der Spring Boot-API ab.

TwitterAnalysis.vue


<template>
    <div id="twitter-analysis">
        <input v-model="query" placeholder="Bitte geben Sie ein Schlüsselwort ein" style="width:400px;">
        <button @click="analyzeProfile" style="margin-left:10px;">Analyse</button>
        <wordcloud
            :data="analyzedWords"
            nameKey="name"
            valueKey="value"
            color="Accent"
            :showTooltip="true"
            :wordClick="wordClickHandler">
        </wordcloud>
    </div>
</template>

<script>
import wordcloud from 'vue-wordcloud'
import axios from 'axios'
axios.defaults.withCredentials = true

export default {
    name: 'TwitterAnalysis',
    components: {
        wordcloud
    },
    data() {
        return {
            query: '',
            analyzedWords: [],
        }
    },
    methods: {
        wordClickHandler(name, value, vm) {
            console.log('wordClickHandler', name, value, vm);
        },
        analyzeProfile: async function () {
            if (this.query == null || this.query === '') return
            await axios.get('http://localhost:<Portnummer der Spring Boot-Ausführungsumgebung>/api/twitter/analysis/profile/by/'
                    + encodeURIComponent(this.query))
                .then(res => {
                    if (res.data != null) {
                        this.analyzedWords = res.data
                    }
                })
                .catch(err => {
                    alert(err + 'Dies ist ein Fehler.')
                })
        },
    },
}
</script>

router/index.js


import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'TwitterAnalysis',
    component: () => import(/* webpackChunkName: "twitteranalysis" */ '../views/TwitterAnalysis.vue')
  },
]

const router = new VueRouter({
  mode: 'history',
  routes
})

export default router

mit diesem http: // localhost: <Portnummer der Ausführungsumgebung von Vue.js> / ` Zugreifen.

図2.PNG

Wenn Sie ein Suchwort eingeben und die Analysetaste drücken

図3.PNG

Erfolg! Sollte tun.

Wenn Sie es sich ansehen, gibt es Wörter, die keine Rolle spielen, wie z. B. Schrägstrich und http. Ich bin also sicher, dass Sie diese ausschließen werden.

Ich habe mich gefragt, ob diese App einige interessante Trends zeigen könnte, aber ich verstehe das nicht wirklich!

Erstens fühlt es sich so an.

Es scheint, dass Sie viel lernen müssen ...

Recommended Posts

Ich habe versucht, eine Webanwendung zu erstellen, die Tweets mit einer Vue-Word-Cloud durchsucht und die Tendenz untersucht, was im zugehörigen Profil geschrieben steht
Ich habe ein Programm erstellt, das aus dem mit Java überladenen Prozess nach der Zielklasse sucht
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen
Ich habe versucht, eine Webanwendung voller Fehler mit Kotlin zu implementieren
Ich habe einen RESAS-API-Client in Java erstellt
Ich habe versucht, eine Webanwendung aus anderthalb Monaten Programmier-Lerngeschichte zu entwickeln
Ich habe versucht, die Cache-Funktion von Application Container Cloud Service in der lokalen Umgebung zu entwickeln
Ich habe versucht, die Ergebnisse vor und nach der Date-Klasse mit einer geraden Zahl auszudrücken
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 2 ~ Grundlegende Schreibweise für Dash ~ erstellt
Ich habe versucht, eine Anwendung für maschinelles Lernen mit Dash (+ Docker) Teil 1 ~ Umgebungskonstruktion und Funktionsprüfung ~ zu erstellen
Ich habe versucht, ein Beispielprogramm mit dem Problem des Datenbankspezialisten für domänengesteuertes Design zu erstellen
Ich habe versucht, ein übergeordnetes Wertklasseobjekt in Ruby zu erstellen
[iOS] Ich habe versucht, mit Swift eine insta-ähnliche Verarbeitungsanwendung zu erstellen
Ich habe versucht, mit AI "A3RT" eine Talk-App in Java zu erstellen.
Ich habe versucht, die Geschwindigkeit von Graal VM mit JMH zu messen und zu vergleichen
Ubuntu 18 ist das Betriebssystem, das einer Serverinstanz in der Sakura-Cloud eine Netzwerkkarte hinzufügt und eine lokale IP zuweist.
Lassen Sie uns eine TODO-Anwendung mit Java 2 erstellen. Ich möchte eine Vorlage mit Spring Initializr erstellen und eine Hello-Welt erstellen
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 3 ~ Übung ~ erstellt
Was ich versucht habe, als ich alle Felder einer Bohne bekommen wollte
Ich habe versucht, die Telefonnummer (Festnetz / Mobiltelefon) mit einem regulären Ausdruck in Rails auszudrücken und Validierung und Test zu schreiben
Ich habe versucht, ein Tool zum Vergleichen von Amazon-Produktpreisen auf der ganzen Welt mit Java, der Amazon Product Advertising API und der Currency API (29.01.2017) zu erstellen.
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht zu erklären, was Sie aus Anfängersicht in einer beliebten Sprache für die Webentwicklung tun können.
Was ist der Unterschied zwischen den Verantwortlichkeiten der Domänenschicht und der Anwendungsschicht in der Zwiebelarchitektur [DDD]?
[Java] Ich habe versucht, ein Janken-Spiel zu erstellen, das Anfänger auf der Konsole ausführen können
[Rails] So speichern Sie die Anforderungs-URL eines Benutzers, der nicht angemeldet ist, vorübergehend und kehren nach der Anmeldung zu dieser URL zurück
Ein Programm, das nach einer Zeichenfolge sucht und die Suchzeichenfolge gefunden hat, zeigt die Zeichenfolge vom Zeilenanfang bis kurz vor der Suchzeichenfolge an.
Ich habe versucht, innerhalb von 3 Monaten einen Antrag von unerfahren zu stellen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Ich habe versucht, dies und das von Spring @ Transactional zu überprüfen
Ich möchte eine Liste mit Kotlin und Java erstellen!
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich habe JAX-RS ausprobiert und mir das Verfahren notiert
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Ich habe versucht, ein Fenster mit Bootstrap 3 zu erstellen"
Nachdem ich Progate gelernt hatte, versuchte ich, eine SNS-Anwendung mit Rails in der lokalen Umgebung zu erstellen
Eine Notiz von dem, worauf ich gestoßen bin und was ich beim Aufholen von Laravel von Rails bemerkt habe
Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser
Ich habe versucht, das Problem der "mehrstufigen Auswahl" mit Ruby zu lösen
Ich habe versucht, den Weihnachtsbaum in einem Lebensspiel zu beleuchten
Ich habe versucht, eine Kreditkartenhandelsanwendung mit Corda 1 auszuführen
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
Ich habe versucht, die Cache-Funktion des Application Container Cloud Service zu verwenden
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, den Betrieb des gRPC-Servers mit grpcurl zu überprüfen
Eine Geschichte, die mit der Einführung von Web Apple Pay zu kämpfen hatte
Ich habe versucht, die Methoden von Java String und StringBuilder zusammenzufassen
So identifizieren Sie den Pfad, auf dem leicht Fehler gemacht werden können
Ich habe versucht, einen Numeron zu erstellen, der mit Ruby nicht gut ist
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen
Erstellen einer ArrayList, mit der Sie die Koordinaten einer zweidimensionalen Ebene eingeben und abrufen können
Ich habe versucht, die letzten 10 Fragen zu lösen, die nach der Registrierung bei AtCoder in Java gelöst werden sollten