classifier.py 설계부분의 classifier 모듈을 구현하였다. classifier 라는 클래스가 하나 있으며 그 클래스를 통해 댓글이 선플인지 악플인지 판단한다. 클래스 외부에서는 classify라는 멤버함수에 덧글을 넘겨 호출하면 숫자를 하나 리턴받는데 그 수가 양수면 선플이고 그렇지 않으면 악플이다.
def classify(self, comment):
# build wordiddic -> { wordid:frequency, wordid:frequency, ... }
worddic = getterms(comment)
words = worddic.keys()
wordiddic = {}
for word in words:
cur = self.con.execute("select rowid from wordlist where word = '%s'" % umbcs(word))
res = cur.fetchone()
if res == None: continue # ignore unadded words
else: wordiddic[res[0]] = worddic[word]
# build line -> "0 wordid:frequency worid:frequency ..." (wordid asc)
line = "0 "
for wordid, frequency in sorted(wordiddic.items(), key=lambda item:item[0]):
line = line + str(wordid) + ":" + str(frequency) + " "
return svmclassifier(line + "\n")
getterms 은 댓글을 입력하면 명사와 그 댓글에서의 명사 출현회수를 담은 사전을 리턴하고 svmclassifier 는 댓글을 단어 출현횟수를 자질로 백터화해서 넘기면 악플 집단인지 선플집단인지 분류해준다.
analyzer.py
설계부분의 analyzer 모듈을 구현하였다. analyzer 라는 클래스가 하나 있으며 그 클래스를 통해 데이터셋을 분석한다. 클래스 외부에서는 probability 라는 멤버함수에 단어를 넘겨 호출하면 문자열을 하나 리턴받는데 단어가 데이터셋에 없을 경우 "no data"를 그렇지 않을경우 단어가 악플에 포함되었을 확률이다.
def probability(self, term):
# get wordid
res = self.con.execute("select rowid from wordlist where word = '%s'" % umbcs(term)).fetchone()
if res == None: return "no data"
else: wordid = res[0]
# get case -> [-1, 1, ...] (-1 : bad, 1 : good)
case = []
for commentid in self.con.execute("select commentid from wordlocation where wordid = %d" % wordid).fetchall():
for status in self.con.execute("select status from commentlist where rowid = %d" % commentid[0]).fetchall():
case.append(status[0])
# return -> "no data" or "48%"
return str(int((case.count(-1) / float(len(case))) * 100)) + "%"
성능을 고려하지 않고 작성하였으며 댓글이 10만개가 넘어갈 경우 재작성 되어야 할 것이다. 아마 데이터 베이스를 갈아타거나 적절히 여러파일로 나눠서 처리해야 할 것이다. 데이터베이스에서 해당단어가 포함된 댓글을 가져와서 악플의 수를 모든댓글의 수로 나누었다.
result
위 두함수를 이용해서 간단한 악플판별 웹페이지를 작성하였다. python 으로 작성하였고 django 프레임웍을 이용하였다. 국내호스팅중 django를 지원하는 호스팅이 없기때문에 안타깝게도 스크린샷을 으로 대체한다.
Trackback URL : http://naragoing.tistory.com/trackback/16