[django] 국립국어원 한국어 기초 사전 다루기 (3)

0v0baek·2023년 6월 19일
0

TIP

목록 보기
12/15
post-custom-banner

참고 사이트

국립국어원 한국어 기초사전

순서

DB에 데이터 저장 후 추출 vs API로 호출해오기 : 둘 중 더 효율적인 것은?
✅ DB에 데이터 저장하는 방법 고안 & 초기 세팅
👉 json 값에서 원하는 정보만 추출해서 DB에 담기

3. json 값에서 원하는 정보만 추출해서 DB에 담기

DB에 코드를 담을 때 가장 어려운 것은
얽히고 섥혀있는 json 구조를 파악하고
예외사항을 try except 구문으로 막아줘야 한다는 점이었다.

그래서 코드가 많이 길어졌다...

🔎 전체 코드

import json
import os
import re
from dotenv import load_dotenv

# dotenv에서 key값을 참조하기 때문에 dotenv를 load 해와야 함
dotenv_path = os.path.join(os.path.dirname(__file__), ".env")
load_dotenv(dotenv_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

import django

django.setup()

from crawled_data.models import KrDictQuiz, KrDictQuizExample, KrDictQuizExplain

# 파일 바뀔 때 마다 경로 바꿔서 설정
with open(
    "F:/nbc/final_project/전체 내려받기_한국어기초사전_JSON_20230612/1079331_51959.json",
    "r",
    encoding="utf-8",
) as file:
    data = json.load(file)

word_list = data["LexicalResource"]["Lexicon"]["LexicalEntry"]
pattern = r"[^\w\s]"

def kr_dict():
    word_data = []

    for i in range(len(word_list)):
        # word 단어
        my_word = ""
        lemma = word_list[i]["Lemma"]
        if isinstance(lemma, list):
            for item in lemma:
                if item["feat"]["att"] == "writtenForm":
                    my_word = item["feat"]["val"]
        else:
            my_word = lemma["feat"]["val"]
        # 특수문자가 포함된 단어는 제외
        if re.findall(pattern, my_word):
            continue

        # explain과 example
        sense = word_list[i]["Sense"]
        if isinstance(sense, list):
            feats = [sense[j]["feat"] for j in range(len(sense))]
            sense_examples = []
            for k in range(len(sense)):
                try:
                    sense_examples.append(sense[k]["SenseExample"])
                except KeyError:
                    sense_examples.append(None)

        else:
            feats = sense["feat"]
            try:
                sense_examples = [sense["SenseExample"]]
            except KeyError:
                sense_examples = None

        my_explain = []
        if isinstance(feats, list):
            for feat in feats:
                if isinstance(feat, list):
                    for item in feat:
                        if item["att"] == "definition":
                            my_explain.append(item["val"])
                else:
                    my_explain.append(feat["val"])
        else:
            if feats["att"] == "definition":
                my_explain.append(feats["val"])

        # difficulty 난이도
        # 0(없음), 1(초급), 2(중급), 3(고급)
        my_difficulty = 0
        try:
            feat = word_list[i]["feat"]
            dif = {"없음": 0, "초급": 1, "중급": 2, "고급": 3}
            if isinstance(feat, list):
                for item in feat:
                    if item["att"] == "vocabularyLevel":
                        my_difficulty = dif[item["val"]]
            else:
                if feat.get("att") == "vocabularyLevel":
                    my_difficulty = dif[feat["val"]]
        except KeyError:
            pass

        # example 단어 예시 - type, contents
        my_all_examples = []
        if sense_examples is not None:
            for examples in sense_examples:
                if examples is not None:
                    if isinstance(examples, list):
                        for example in examples:
                            skip_example = False
                            for ex in example["feat"]:
                                # "대화"인 경우에는 현재의 example을 건너뜀
                                if ex["val"] == "대화":
                                    skip_example = True
                                    break
                                if ex["att"] == "type":
                                    my_type = ex["val"]
                                elif ex["att"] == "example":
                                    my_content = ex["val"]
                            if not skip_example:
                                my_all_examples.append({my_type: my_content})
                    else:
                        for ex in examples["feat"]:
                            if ex["att"] == "type":
                                my_type = ex["val"]
                            elif ex["att"] == "example":
                                my_content = ex["val"]
                        my_all_examples.append({my_type: my_content})

        complete_word = {
            "word": my_word,
            "explain": my_explain,
            "difficulty": my_difficulty,
            "example": my_all_examples,
        }

        word_data.append(complete_word)
    return word_data


if __name__ == "__main__":
    dict_words = kr_dict()
    for dict_word in dict_words:
        my_word = KrDictQuiz(word=dict_word["word"], difficulty=dict_word["difficulty"])
        my_word.save()
        for explain in dict_word["explain"]:
            my_explain = KrDictQuizExplain(dict_word=my_word, content=explain)
            my_explain.save()
        for example in dict_word["example"]:
            if "구" in example:
                my_type = 0
                my_content = example["구"]
            if "문장" in example:
                my_type = 1
                my_content = example["문장"]
            my_example = KrDictQuizExample(
                dict_word=my_word, word_type=my_type, content=my_content
            )
            my_example.save()
    print("데이터 베이스에 저장 완료!!")

정규표현식으로 특수문자가 들어가는 단어를 제외하고 크롤링 할 수 있게 했다.
그리고 대화형식을 제외하고 예시를 수집했다.

나머지는 대부분 예외 사항 처리.. 위치 찾기.. 오류 처리 이런식이라서 저번과 크게 다를 것 없다.

그리고 파일을 직접 실행했을때만 모델에 저장할 수 있게 if __name__ == "__main__" 구문을 넣어 처리해주었다.

profile
개발 공부 하는 비전공자 새내기. 꾸준히 합시다!
post-custom-banner

0개의 댓글