안녕하세요. 언제나 휴일, 언휴예요.
이전 강의에서 뉴스 크롤링 라이브러리 제작을 마쳤습니다.
이제 수집한 뉴스를 분석하는 코드를 작성할 시점이 왔어요.
이번에 문장으로 만들어진 콘텐츠를 분석할 때 가장 기초적인 형태소 분석을 해 볼 거예요.
자세한 내용은 동영상 강의를 참고하세요.
2020년 5월 4일 저녁 7시 30분 경에 “스포츠”로 검색하여 나오는 1100개의 기사 중에 가장 많이 나온 단어 BEST 50입니다. *참고로 각 기사의 앞 부분만 발췌하기 때문에 빈도 수가 크지 않습니다.*
- 스포티비뉴스:33
- KBO:33
- 손진아:33
- 첫:34
- 예정:34
- 최고:35
- 활동:35
- 트랙스:35
- 교육기부:36
- 모델:38
- 72개월:38
- 스포츠마케팅:39
- 한도:40
- 대표적인:40
- 후원:42
- 관계자:43
- 개막전:45
- 5일:46
- 사진:47
- SUV:47
- 개막:49
- 연계:50
- 지원:51
- 브랜드:51
- 옥영화:51
- 마케팅:52
- 잠실야구장에서:54
- 대비:55
- 오전:60
- 출시:60
- KBO리그:63
- 미국:64
- 경기:66
- 잠실:68
- 선수:69
- 렉스턴:69
- 트윈스:72
- 스포츠투데이:75
- 시즌:77
- 훈련:81
- 코로나19:82
- 두산:87
- LG:88
- 2020:93
- 프로야구:117
- 매경닷컴:127
- MK스포츠:130
- 기자:207
- 4일:216
- 스포츠:442
- Morpheme.cs
using System; namespace 형태소_분석기_만들기 { /// /// 형태소 /// public class Morpheme:IComparable { /// /// 형태소 단어 - 가져오기 및 설정하기 /// public string Name { get; set; } /// /// 빈도수 - 가져오기 및 설정하기 /// public int Count { get; set; } /// /// 형태소 생성자 /// ///단어 ///빈도수 public Morpheme(string name,int count) { Name = name; Count = count; } /// /// ToString 재정의 /// /// 단어 public override string ToString() { return Name; } /// /// 비교 - 정렬을 위해 제공 /// ///비교 대상 - 형태소 형식 개체여야 함 /// 비교 결과 public int CompareTo(object obj) { Morpheme mo = obj as Morpheme; if(mo == null) { throw new ApplicationException("비교 대상 개체는 Morpheme 형식이어야 합니다."); } return Count.CompareTo(mo.Count); } } }
- MorphemeParser.cs
using System; using System.Collections.Generic; namespace 형태소_분석기_만들기 { /// /// 형태소 분석기 - 정적 클래스 /// public static class MorphemeParser { static string[] filters = {"~","!","#","$","%","^","&","*","(",")","-","_","=","+","|",@"\", "{","}","[","]",";",":","\"","'","<",">",",",".","/","?"," ","","quot","amp","apos","lt","gt"}; static string[] pf_filters = { "는", "은", "을", "를", "가", "에", "게", "에게","의","들","있다.","없다","이다","입니다", "합니다" , "합시다"}; /// /// 형태소 분석 메서드 /// ///원본 문자열 /// 형태소 컬렉션 public static List Parse(string source) { List mlist = new List(); string[] elems = source.Split(filters, StringSplitOptions.RemoveEmptyEntries); foreach(string elem in elems) { ParseElem(elem, mlist); } mlist.Sort(); return mlist; } private static void ParseElem(string elem, List mlist) { if(elem == string.Empty) { return; } foreach(string pf_filter in pf_filters) { if(elem.EndsWith(pf_filter)) { MakeElem(pf_filter, elem, mlist); return; } } RecordElem(elem, mlist); } private static void RecordElem(string elem, List mlist) { foreach(Morpheme mo in mlist) { if(mo.Name == elem) { mo.Count++; return; } } Morpheme mo2 = new Morpheme(elem, 1); mlist.Add(mo2); } private static void MakeElem(string pf_filter, string elem, List mlist) { int pos = elem.Length - pf_filter.Length; string sub = elem.Substring(0, pos); RecordElem(sub, mlist); } /// /// 형태소 통합 메서드 /// ///원본 형태소 컬렉션 ///타겟 형태소 컬렉션 /// 타겟 형태소 컬렉션 public static List Merge(List src, List dest) { foreach(Morpheme mo in src) { RecordElem2(mo, dest); } dest.Sort(); return dest; } private static void RecordElem2(Morpheme mo, List dest) { foreach(Morpheme mo2 in dest) { if(mo2.Name == mo.Name) { mo2.Count += mo.Count; return; } } dest.Add(mo); } } }
- Program.cs
using System; using System.Collections.Generic; using 네이버_뉴스_크롤링_라이브러리_제작; namespace 형태소_분석기_만들기 { class Program { static void Main(string[] args) { string id = [네이버 개발자센터에서 발급받은 애플리케이션 ID]; string secret = [네이버 개발자센터에서 발급받은 애플리케이션 Secret]; NaverNews nn = new NaverNews(id, secret); int total = nn.Find("스포츠"); Console.WriteLine(total); List morphemes = new List(); List src_morphemes; List nc; for (int start = 1; (start < 1000) && (start < total); start += 100) { nc = nn.FindNews(start, 100); foreach (News news in nc) { Console.WriteLine(news.Title); Console.WriteLine("=="); Console.WriteLine(news.Description); Console.WriteLine("=================================================="); src_morphemes = MorphemeParser.Parse(news.Description); MorphemeParser.Merge(src_morphemes, morphemes); } } foreach(Morpheme morpheme in morphemes) { Console.WriteLine("{0}:{1}", morpheme, morpheme.Count); } } } }
*이전 강의에서 작성한 뉴스 크롤링 라이브러리를 참조 추가하셔야 합니다.*