[JAVA] J'ai essayé de créer une application Web qui recherche les tweets avec vue-word cloud et examine la tendance de ce qui est écrit dans le profil associé

C'est celui que vous voyez souvent.

Je vais vous montrer le résultat en premier pour ceux qui disent ce que c'est.

図1.PNG

Lorsque vous recherchez un tweet par mot de recherche, le mot du profil de la personne qui a tweeté le hit est affiché dans le nuage de tags de Word Cloud.

Les caractères qui apparaissent fréquemment seront plus grands.

Cela semble facile à faire, mais quand je le recherche, c'est surtout Python.

En ce moment, je développe avec Vue.js et Java (Spring Boot), alors j'ai pensé que je pourrais le faire avec ça, alors j'ai créé une petite application Web.

Cette fois, je tire le contenu du profil du contenu du tweet, pas du contenu du tweet, ce qui peut être un peu délicat.

Journées de création d'applications Web: 2 jours Création d'article Qiita: 2 jours

La création d'article Qiita est plus difficile.

Pourquoi le titre est-il resté si long?

Le flux de fonctionnement de l'application Web est comme ça.


Obtenez des informations de profil sur les tweets avec l'API Twitter ↓ Analyse morphologique des informations de profil ↓ Visualisation
Qu'est-ce que l'analyse morphologique?

Cela ressemble à diviser une phrase en mots, mais je n'en sais pas beaucoup plus, donc je suis sûr que vous serez plus familier.

2. Environnement

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 est l'avant et Spring Boot est l'API côté serveur sans aucune discipline.

La structure approximative des répertoires ressemble à ceci.

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

3. Procédure

3-1. Prémisse

Un projet Spring Boot a été créé.

3-2. Application d'utilisation de l'API Twitter

Tout d'abord, vous devez demander l'utilisation de l'API Twitter du côté Twitter.

On suppose que vous avez un compte Twitter.

Il existe un site qui explique gentiment, veuillez donc vous y référer lors de la demande d'utilisation. Explication détaillée de la phrase d'exemple de l'application d'utilisation de l'API Twitter version 2020 jusqu'à l'acquisition de la clé API

Les informations changent de jour en jour, elles peuvent donc avoir changé, mais cela devrait probablement être plus facile.

Tout ce que vous avez à faire est de répondre à quelques questions du côté Twitter.

Bien sûr, l'écran de l'application est obligé d'écrire en anglais, mais en fait il peut être en japonais ...

Quand j'ai répondu à la question, j'ai pensé que j'attendais l'approbation ... mais ce n'était pas le cas, et j'ai pu accéder immédiatement à l'écran d'affichage du Token (Bearer Token).

Tout ce que vous avez à faire est de copier ce jeton et la clé.

Il semble qu'il a fallu plusieurs jours pour attendre l'approbation il y a quelque temps.

3-3. Implémentation Java

Tout d'abord, obtenez des informations de profil à l'aide de l'API de Twitter.

Il semble pratique d'utiliser une bibliothèque appelée Twitter4J, mais je ne l'ai pas utilisée cette fois.

Il n'y a pas de raison particulière.

L'URL de l'API ressemble à ceci.

Il semble que l'API a été récemment mise à jour.

https://api.twitter.com/2/tweets/search/recent?expansions=author_id&user.fields=description&max_results=100&query=<Mot-clé de recherche>
Paramètres utilisés cette fois Contenu
expansions=author_id Désigné pour obtenir des informations sur la personne qui a rédigé le tweet en même temps que le texte du tweet
user.fields=description Spécifié pour inclure le texte du profil de la personne qui a tweeté dans les informations à acquérir
max_results=100 Nombre maximum d'acquisitions
query= ツイートに対するRechercher un mot

Pour plus de détails, voir Site officiel

Donc, obtenir des informations à l'aide de l'API est comme ça.

Pour le jeton, spécifiez le jeton porteur obtenu ci-dessus.

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 = <jeton>;

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

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;
    }
}

Ensuite, l'analyse morphologique, si vous voulez le faire en Java, Kuromoji est pratique.

Ajoutez simplement une ligne au fichier build.gradle.

build.gradle


dependencies {
~ Abréviation ~
    implementation 'com.atilika.kuromoji:kuromoji-ipadic:0.9.0'
~ Abréviation ~
}

De plus, en ce qui concerne le format pour renvoyer les données, puisque vue-wordcloud gère le tableau des objets avec "nom" et "valeur" comme clés dans la vue, "nom" et "valeur" sont utilisés comme clés. Renvoie un tableau d'objets en JSON.

Saisissez le mot suite à une analyse morphologique dans «nom» et le nombre de fois où le mot apparaît dans «valeur».

Cette fois, ne ciblant que la nomenclature, en plus d'accéder à l'API ci-dessus, une analyse morphologique a été effectuée pour créer un objet avec "nom" et "valeur" dans les champs comme suit.

Utilisez la classe Tokenizer pour l'analyse morphologique.

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 = <jeton>;

        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("nom"))
                .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 compatible ici pour l'application de test
        HttpHeaders headers = new HttpHeaders();
        headers.add("Access-Control-Allow-Credentials", "true");
        headers.add("Access-Control-Allow-Origin", "http://localhost:<Vue.js numéro de port de l'environnement d'exécution>");

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

Je suis sûr qu'il existe un moyen plus simple si vous n'utilisez pas Twitter4J en Java!

Je suis sûr qu'il existe un tel échantillon quelque part.

Malheureusement, cette fois, c'était mon échantillon.

3-4. Implémentation de Vue.js

C'est facile car vous installez simplement vue-wordcloud et copiez et collez la source officielle vue-wordcloud.

Créez un projet avec l'interface graphique vue-cli et placez-le à l'emplacement de la structure de répertoires ci-dessus.

Ensuite, installez vue-word cloud avec l'interface graphique vue-cli.

Oh, et axios aussi.

Après cela, copiez et collez l'exemple officiel, corrigez-le un peu et récupérez les données de l'API Spring Boot.

TwitterAnalysis.vue


<template>
    <div id="twitter-analysis">
        <input v-model="query" placeholder="Veuillez saisir un mot-clé" style="width:400px;">
        <button @click="analyzeProfile" style="margin-left:10px;">une 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:<Numéro de port de l'environnement d'exécution Spring Boot>/api/twitter/analysis/profile/by/'
                    + encodeURIComponent(this.query))
                .then(res => {
                    if (res.data != null) {
                        this.analyzedWords = res.data
                    }
                })
                .catch(err => {
                    alert(err + 'Ceci est une erreur.')
                })
        },
    },
}
</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

avec ça http: // localhost: <numéro de port de l'environnement d'exécution Vue.js> / Accéder.

図2.PNG

Lorsque vous entrez un mot de recherche et appuyez sur le bouton d'analyse

図3.PNG

Succès! Devrait faire.

Si vous le regardez, il y a des mots qui n'ont pas d'importance, tels que slash et http, donc je suis sûr que vous les excluerez.

Je me demandais si cette application pouvait montrer des tendances intéressantes, mais je ne comprends pas vraiment!

En premier lieu, c'est comme si c'était le cas.

Il semble que vous ayez besoin d'étudier beaucoup ...

Recommended Posts

J'ai essayé de créer une application Web qui recherche les tweets avec vue-word cloud et examine la tendance de ce qui est écrit dans le profil associé
J'ai créé un programme qui recherche la classe cible à partir du processus surchargé avec Java
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot
J'ai essayé d'implémenter une application web pleine de bugs avec Kotlin
J'ai créé un client RESAS-API en Java
J'ai essayé de développer une application web à partir d'un mois et demi d'histoire d'apprentissage de la programmation
J'ai essayé de développer la fonction de cache d'Application Container Cloud Service dans l'environnement local
J'ai essayé d'exprimer les résultats avant et après de la classe Date avec une ligne droite numérique
J'ai créé une application d'apprentissage automatique avec Dash (+ Docker) part2 ~ Façon basique d'écrire Dash ~
J'ai essayé de créer une application d'apprentissage automatique avec Dash (+ Docker) part1 ~ Construction de l'environnement et vérification du fonctionnement ~
J'ai essayé de créer un exemple de programme en utilisant le problème du spécialiste des bases de données dans la conception pilotée par domaine
J'ai essayé de créer une classe parent d'objet de valeur dans Ruby
[iOS] J'ai essayé de créer une application de traitement de type insta avec Swift
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
J'ai essayé de mesurer et de comparer la vitesse de Graal VM avec JMH
Ubuntu 18 est le système d'exploitation qui ajoute une carte réseau à une instance de serveur dans le cloud de Sakura et attribue une adresse IP locale.
Faisons une application TODO avec Java 2 Je veux créer un modèle avec Spring Initializr et créer Hello world
J'ai créé une application d'apprentissage automatique avec Dash (+ Docker) part3 ~ Practice ~
Ce que j'ai essayé quand je voulais obtenir tous les champs d'un haricot
J'ai essayé d'exprimer le numéro de téléphone (téléphone fixe / téléphone portable) avec une expression régulière dans Rails et d'écrire la validation et le test
J'ai essayé de créer un outil de comparaison des prix des produits Amazon dans le monde entier avec Java, l'API Amazon Product Advertising, l'API Currency (29/01/2017)
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé d'expliquer ce que vous pouvez faire dans un langage populaire pour le développement Web du point de vue d'un débutant.
Quelle est la différence entre les responsabilités de la couche domaine et de la couche application dans l’architecture onion [DDD]
[Java] J'ai essayé de créer un jeu Janken que les débutants peuvent exécuter sur la console
[Rails] Comment enregistrer temporairement l'URL de demande d'un utilisateur qui n'est pas connecté et revenir à cette URL après la connexion
Un programme qui recherche une chaîne de caractères, et lorsque la chaîne de caractères de recherche est trouvée, affiche la chaîne de caractères du début de la ligne juste avant la chaîne de caractères de recherche.
J'ai essayé de faire une demande en 3 mois d'inexpérimenté
J'ai essayé de moderniser une application Java EE avec OpenShift.
J'ai essayé de résumer les bases de kotlin et java
J'ai essayé de vérifier ceci et celui de Spring @ Transactional
Je veux faire une liste avec kotlin et java!
Je veux créer une fonction avec kotlin et java!
J'ai essayé JAX-RS et pris note de la procédure
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "J'ai essayé de créer une fenêtre avec Bootstrap 3"
Après avoir appris Progate, j'ai essayé de créer une application SNS en utilisant Rails dans l'environnement local
Une note de ce sur quoi j'ai trébuché et remarqué en rattrapant Laravel de Rails
Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web
J'ai essayé de résoudre le problème de la "sélection multi-étapes" avec Ruby
J'ai essayé d'illuminer le sapin de Noël dans un jeu de la vie
J'ai essayé d'exécuter une application d'échange de cartes de crédit avec Corda 1
J'ai essayé de créer un environnement de serveur UML Plant avec Docker
J'ai essayé d'utiliser la fonction de cache d'Application Container Cloud Service
J'ai essayé de créer une application Android avec MVC maintenant (Java)
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
Une histoire qui a eu du mal avec l'introduction de Web Apple Pay
J'ai essayé de résumer les méthodes de Java String et StringBuilder
Comment identifier le chemin sur lequel il est facile de se tromper
J'ai essayé de faire un Numeron qui n'est pas bon avec Ruby
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
Créer une ArrayList qui vous permet de lancer et de récupérer les coordonnées d'un plan bidimensionnel
J'ai essayé de résoudre les 10 dernières questions qui devraient être résolues après m'être inscrit auprès d'AtCoder en Java