Elk Toy Project 국민청원 데이터 분석

이동명·2023년 6월 28일
0
post-thumbnail

# 1 청와대 데이터 다운로드


깃헙에서 데이터 다운로드

https://github.com/lovit/petitions_archive

다운 받으면 cmd로 해당 폴더 경로내에서

window - ren petitions_201* .json
linux -ls petitions_201
| xargs -i mv {} {}.json

명령어를 통해 파일명 끝에 .json 을 붙여주자

# 2 데이터 수동 업로드

  • 받은 파일의 데이터의 확장자를 모두 .json 으로 변경

그리고 표시된 부분에 들어간다.

그리고 이곳에 파일을 드래그 해서 import 하고 index를 지정해주기만 하면된다.

# 3 데이터 자동 업로드

근데 관건은 여러개의 파일이 올라가지 않는다는 사실.. 다 올리려면 1시간도 넘게 걸리겠는데 누가 이렇게 할까? 그래서 한꺼번에 _bulk 로 올릴거임..

하지만 _bulk를 사용하려면 현재 데이터의 포맷을 _bulk 가능한 형태로 바꾸어야 한다.

앞서 간단히 살펴보았는데 위에는 첫줄에는 index와 id등 어떤 명령을 전달할 것인지가 먼저 명시돼야 하고 두번째 줄에는 전달하는 명령에 필요한 데이터를 넣어야 한다. 그러나 우리가 전달한 json 파일은 데이터만 입력돼 있으므로 이를 변경할 필요가 있다.

아래의 "{"category""을 "{"index":{"_index": "" + fileName + ""}}\n{"category""로 대체 하는 클래스를 만들어서 돌리자..

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

public class JsonToEsBatchConverter {

    public static void main(String[] args) {
        String directoryPath = "./";
        convertJsonToEsBatch(directoryPath);
    }

    public static void convertJsonToEsBatch(String directoryPath) {
        try {
            Files.walk(Paths.get(directoryPath))
                    .filter(Files::isRegularFile)
                    .forEach(path -> {
                        String fileName = path.getFileName().toString();
                        if (fileName.startsWith("petitions")) {
                            System.out.println(path.toString());
                            jsonToEsBatch(path.toString(), fileName);
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void jsonToEsBatch(String filePath, String fileName) {
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath, StandardCharsets.UTF_8))) {
            StringBuilder data = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                data.append(line).append("\n");
            }

            String modifiedData = data.toString().replace("{\"category\"", "{\"index\":{\"_index\": \"" + fileName + "\"}}\n{\"category\"");

            String outputPath = filePath + ".bat";
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath, StandardCharsets.UTF_8))) {
                writer.write(modifiedData);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

성공적으로 .bat 파일을 뱉어내는 모습

이후 cmd 에서 UTF-8 설정에서 애를 먹다가 bash shell 을 이용하였고


ls *.bat | xargs -i curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @{}

으로 해결하였다.

데이터의 성공응답을 받은 모습

그리고 Kibana에서 데이터가 성공적으로 들어온 모습

그리고 패턴을 등록 해줄건데 시계열 데이터를 begin(청원이 시작된 때) 으로하자

그리고 대시보드에서 약 21만개의 국민청원 데이터를 볼 수 있다.

# 4 한국어 형태소 nori 분석기 적용

일단 타입의 혼동을 막기 위해서... .bat 파일을 전부 삭제하고 replace 부분만 형식을 바꿔서
다시한번 bat 파일을 뽑아내자.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

public class JsonToEsBatchConverter {

    public static void main(String[] args) {
        String directoryPath = "./";
        convertJsonToEsBatch(directoryPath);
    }

    public static void convertJsonToEsBatch(String directoryPath) {
        try {
            Files.walk(Paths.get(directoryPath))
                    .filter(Files::isRegularFile)
                    .forEach(path -> {
                        String fileName = path.getFileName().toString();
                        if (fileName.startsWith("petitions")) {
                            System.out.println(path.toString());
                            jsonToEsBatch(path.toString(), fileName);
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void jsonToEsBatch(String filePath, String fileName) {
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            StringBuilder data = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                data.append(line).append("\n");
            }

            String modifiedData = data.toString().replace("{\"category\"", "{\"index\":{\"_index\": \"" + fileName + "\", \"_type\":\"_doc\"}}\n{\"category\"");

            String outputPath = filePath + ".bat";
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath))) {
                writer.write(modifiedData);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

그리고 data Mapping 을 해주자.. text 필드랑 content는 한글이기 때문에 집중적으로 매핑하자.

Mapping 을 해주는 java 클래스를 만들었다.

public class ESIndexSettingsGenerator {

    public static void main(String[] args) {
        StringBuilder data = new StringBuilder();
        for (int year = 17; year <= 19; year++) {
            for (int month = 1; month <= 12; month++) {
                data.append(generateIndexSettings(year, month));
            }
        }
        System.out.println(data.toString());
    }

    public static String generateIndexSettings(int year, int month) {
        return String.format("PUT petitions_20%02d-%02d.json\n" +
                "{\n" +
                "  \"settings\": {\n" +
                "    \"analysis\": {\n" +
                "      \"analyzer\": {\n" +
                "        \"nori\": {\n" +
                "          \"tokenizer\": \"nori_tokenizer\"\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  },\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"content\": {\n" +
                "        \"type\": \"text\",\n" +
                "        \"fields\": {\n" +
                "          \"nori\": {\n" +
                "            \"type\": \"text\",\n" +
                "            \"analyzer\": \"nori\"\n" +
                "          }\n" +
                "        }\n" +
                "      },\n" +
                "      \"title\": {\n" +
                "        \"type\": \"text\",\n" +
                "        \"fields\": {\n" +
                "          \"nori\": {\n" +
                "            \"type\": \"text\",\n" +
                "            \"analyzer\": \"nori\"\n" +
                "          }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}\n", year, month);
    }
}

java ESIndexSettingsGenerator.java > text.txt 로 결과를 txt 파일로 전부 다 받아주고 그대로 전체복사해서 Kibana devTools 에서 매핑하자!

그런데 나는 아직도 nori를 설치를 안했네..설치해주자.. 간단하다.

엘라스틱서치 bin 폴더 경로에서 cmd 를열고

.\elasticsearch-plugin.bat install analysis-nori 명령어사용 후 재실행 ..ok

정상적으로 Mapping이 되는걸 확인 할 수 있다.

순서에 대해서 조금 헤메긴 했지만 결국 형태소 분석기까지 정리하자면

    1. 깃헙에서 데이터를 받는다.
    1. -ls petitions_201* | xargs -i mv {} {}.json 로 .json 붙여준다.
    1. 만들어 놓은 JsonToEsBatchConverter.java 를 이용해서 .bat 파일을 추출해준다. (이 과정속에선 타입의 혼동을 줄이기 위해 "_type" : "_doc" 내용을 추가 하였음)
    1. 한글 형태소 분석기 nori 적용을 위해 자동으로 Mapping 을 해주는 ESIndexSettingsGenerator.java 파일을 이용해서 결과값을 txt 파일로 빼준다음에 모두 Kibana dev tools 에서 추가를 해준다. ( 이 과정속에서 한국어 형태소 분석기 적용을 위한 우리의 필드 중 한국어가 들어가는 content 필드와 title 필드를 Mapping 해준다.)
    1. Mapping 이 다 완료되면 아래의 명령어를 통해 bulk로 밀어넣자

ls *.bat | xargs -i curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @{}

    1. index 패턴을 다 잡아주고 begin(청원이 시작된 날짜) 시계열 데이터로 패턴을 정의하자

그리고 노리적용이 잘 되었는지 검색을 하면서 비교를 해보자..

노리 적용 전 검색

"신변불안" 검색 - 결과없음

"정치 데이터 분석" 검색 ( 의미는 관계없고 단어가 포함된 것만 검색됨)

"사회 문제 데이터 분석" 검색( 의미는 관계없고 단어가 포함된 것만 검색됨)

노리 적용 후 검색

"신변불안" 검색 - 신변불안에 관련한 내용이 검색됨

"정치 데이터 분석" 검색 ( 단순 단어 검색이 아닌 의미가 있는 결과가 나옴)

"사회 문제 데이터 분석" 검색( 단순 단어 검색이 아닌 의미가 있는 결과가 나옴)

# 5 동의어 사전 정의

동의어 사전 필터 전 검색

동의어 사전 필터 후 검색

profile
Web Developer

0개의 댓글