1. 감성분석엔진을 통해 분류된 전체 회사 데이터.

def weekly_all_classified_data(dict):
    start_date,end_date=start_to_date(),end_to_date()
    maximum,minimum=score_input()
    for key,value in dict.items():
        driver = webdriver.Chrome('C:\\Users\\LeeKwanHyeong\\chromedriver_win32\\chromedriver.exe',chrome_options=options)
        driver.implicitly_wait(2)
        driver.get(value)
        # sort 선택창
        elem = driver.find_element_by_xpath("//span[@class='DPvwYc']")
        elem.click()
        time.sleep(3)
        pyautogui.press('up')
        time.sleep(0.7)
        pyautogui.press('up')
        time.sleep(0.7)
        pyautogui.press('enter')
        
        while(True):
            driver.execute_script("window.scrollTo([0],document.body.scrollHeight);")
            time.sleep(0.5)
            try:
                element=driver.find_element_by_xpath('//div[@class="U26fgb O0WRkf oG5Srb C0oVfc n9lfJ"]')
                if(element is not None):
                    element.click()
                    break
            except Exception:
                continue

        html=driver.page_source
        driver.quit()
        bsObj=BeautifulSoup(html,'lxml')
        div_reviews=bsObj.find_all("div",{"class":"d15Mdf bAhLNe"})
        
        
        company_list,grade_list,date_list,content_list=[],[],[],[]
        for div in div_reviews:
            
            

            date_=div.find('span',{"class":"p2TkOb"}).get_text()
            t=re.findall(r"\d*\.\d+|\d+",date_)
            date='{0}-{1}-{2}'.format(t[0],t[1],t[2])
            year, month, day=int(t[0]), int(t[1]), int(t[2])
            dd=datetime(year,month,day)
            if((dd-start_date>=timedelta(days=0)) and (end_date-dd>=timedelta(days=0))):
                content=div.find('span',{'jsname':'bN97Pc'}).get_text()
                content=content.replace("전체 리뷰",'')
                content=re.sub('[^가-힣0-9a-zA-Z_!?@#%^&-=:;,\"\'<>\\s]','',content)
                content.encode('utf-8')
                grade=len(div.find_all('div',{'class':'vQHuPe bUWb7c'}))
                percentage,word=call_GRU_predict.GRU_predict(content)
                if(((percentage<maximum)and (percentage>minimum))) and (len(word)>6):
                    date_list.append(dd)
                    content_list.append(content)
                    grade_list.append(grade)
                    company_list.append(key)
                else:
                    continue
        grade_Series=pd.Series(grade_list)
        date_Series=pd.Series(date_list)
        content_Series=pd.Series(content_list)
                #
        company_Series=pd.Series(company_list)
        data_frame=pd.DataFrame()
        data_frame['company']=company_Series
        data_frame['date']=date_Series
        data_frame['grade']=grade_Series
        data_frame['content']=content_Series
        
        good_data=data_frame[data_frame['grade']>2]
        bad_data=data_frame[data_frame['grade']<3]
        
        writer=pd.ExcelWriter("C:/data/thisweek_classified.xlsx")
        if not os.path.exists(writer):
            good_data.to_excel(writer, sheet_name='good',header=True)
            bad_data.to_excel(writer,sheet_name='bad',header=True)
        else:
            bad_data.to_excel(writer, sheet_name='bad',header=False)
            good_data.to_excel(writer,sheet_name='good',header=False)
        writer.save()
        if not os.path.exists('C:\\Data\\thisweek_classified.csv'):
            data_frame.to_csv('C:\\Data\\thisweek_classified.csv',index=False, mode='w',encoding='utf_8_sig')
        else:
            data_frame.to_csv('C:\\Data\\thisweek_classified.csv',index=False,mode='a',encoding='utf_8_sig',header=False)
    return data_frame
        
    #location='C:\\Data\\thisweek_classified.csv'
   
            
        
def classified_all_data():
    url_dict=call_url.call_url() #url리턴 함수
      #시작일 종료일 지정
    load=call_all_company.weekly_all_classified_data(url_dict)
    return load

 

 

2. 감성분석 엔진을 통해 분류되지 않은 전체 데이터

 

def weekly_all_unclassified_data(dict):
    start_date,end_date=start_to_date(),end_to_date()
    for key,value in dict.items():
        driver = webdriver.Chrome('C:\\Users\\LeeKwanHyeong\\chromedriver_win32\\chromedriver.exe',chrome_options=options)
        driver.implicitly_wait(2)
        driver.get(value)
        # sort 선택창
        elem = driver.find_element_by_xpath("//span[@class='DPvwYc']")
        elem.click()
        time.sleep(3)
        pyautogui.press('up')
        time.sleep(0.7)
        pyautogui.press('up')
        time.sleep(0.7)
        pyautogui.press('enter')
        
        while(True):
            driver.execute_script("window.scrollTo([0],document.body.scrollHeight);")
            time.sleep(0.5)
            try:
                element=driver.find_element_by_xpath('//div[@class="U26fgb O0WRkf oG5Srb C0oVfc n9lfJ"]')
                if(element is not None):
                    element.click()
                    break
            except Exception:
                continue

        html=driver.page_source
        driver.quit()
        bsObj=BeautifulSoup(html,'lxml')
        div_reviews=bsObj.find_all("div",{"class":"d15Mdf bAhLNe"})
        
        
        company_list,grade_list,date_list,content_list=[],[],[],[]
        for div in div_reviews:
            
            

            date_=div.find('span',{"class":"p2TkOb"}).get_text()
            t=re.findall(r"\d*\.\d+|\d+",date_)
            date='{0}-{1}-{2}'.format(t[0],t[1],t[2])
            year, month, day=int(t[0]), int(t[1]), int(t[2])
            dd=datetime(year,month,day)
            if((dd-start_date>=timedelta(days=0)) and (end_date-dd>=timedelta(days=0))):
                content=div.find('span',{'jsname':'bN97Pc'}).get_text()
                content=content.replace("전체 리뷰",'')
                content=re.sub('[^가-힣0-9a-zA-Z_!?@#%^&-=:;,\"\'<>\\s]','',content)
                content.encode('utf-8')
                grade=len(div.find_all('div',{'class':'vQHuPe bUWb7c'}))
                percentage,word=call_GRU_predict.GRU_predict(content)
               
                date_list.append(dd)
                content_list.append(content)
                grade_list.append(grade)
                company_list.append(key)
                
        grade_Series=pd.Series(grade_list)
        date_Series=pd.Series(date_list)
        content_Series=pd.Series(content_list)
                #
        company_Series=pd.Series(company_list)
        data_frame=pd.DataFrame()
        data_frame['company']=company_Series
        data_frame['date']=date_Series
        data_frame['grade']=grade_Series
        data_frame['content']=content_Series
    good_data=data_frame[data_frame['grade']>2]
    bad_data=data_frame[data_frame['grade']<3]
        
    writer=pd.ExcelWriter("C:/data/thisweek_unclassified.xlsx")
    if not os.path.exists(writer):
        good_data.to_excel(writer,sheet_name='good',header=True)
        bad_data.to_excel(writer,sheet_name='bad',header=True)
    else:
        bad_data.to_excel(writer,sheet_name='bad',header=False)
        good_data.to_excel(writer,sheet_name='good',header=False)
    writer.save()
    if not os.path.exists('C:\\Data\\thisweek_unclassified.csv'):
            data_frame.to_csv('C:\\Data\\thisweek_unclassified.csv',index=False, mode='w',encoding='utf_8_sig')
    else:
        data_frame.to_csv('C:\\Data\\thisweek_unclassified.csv',index=False,mode='a',encoding='utf_8_sig',header=False)
    #all_data=pd.read_csv("C:\\Data\\thisweek_unclassified.csv")
    return data_frame
def none_classified_all_data():
    url_dict=call_url.call_url()
    load=call_all_company.weekly_all_unclassified_data(url_dict)
    return load

 

3. 감성분류를 통해 분류된 선택된 회사 데이터

def weekly_selected_classified_data(url,company):
    
    start_date,end_date=start_to_date(),end_to_date()
    maximum,minimum=score_input()
    
    driver = webdriver.Chrome('C:\\Users\\LeeKwanHyeong\\chromedriver_win32\\chromedriver.exe',chrome_options=options)
    driver.implicitly_wait(2)
    driver.get(url)
     # sort 선택창
    elem = driver.find_element_by_xpath("//span[@class='DPvwYc']")
    elem.click()
    time.sleep(3)
    pyautogui.press('up')
    time.sleep(0.7)
    pyautogui.press('up')
    time.sleep(0.7)
    pyautogui.press('enter')
    
        
    while(True):
        driver.execute_script("window.scrollTo([0],document.body.scrollHeight);")
        time.sleep(0.5)
        try:
            element=driver.find_element_by_xpath('//div[@class="U26fgb O0WRkf oG5Srb C0oVfc n9lfJ"]')
            if(element is not None):
                element.click()
                break
        except Exception:
            continue
    html=driver.page_source
    driver.quit()
    bsObj=BeautifulSoup(html,'lxml')
    div_reviews=bsObj.find_all("div",{"class":"d15Mdf bAhLNe"})
    
    
    #
    company_list,grade_list,date_list,content_list=[],[],[],[]
    
    for div in div_reviews:
        date_=div.find('span',{"class":"p2TkOb"}).get_text()
        t=re.findall(r"\d*\.\d+|\d+",date_)
        date='{0}-{1}-{2}'.format(t[0],t[1],t[2])
        year, month, day=int(t[0]), int(t[1]), int(t[2])
        dd=datetime(year,month,day)
        if((dd-start_date>=timedelta(days=0)) and (end_date-dd>=timedelta(days=0))):
                content=div.find('span',{'jsname':'bN97Pc'}).get_text()
                content=content.replace("전체 리뷰",'')
                content=re.sub('[^가-힣0-9a-zA-Z_!?@#%^&-=:;,\"\'<>\\s]','',content)
                content.encode('utf-8')
                grade=len(div.find_all('div',{'class':'vQHuPe bUWb7c'}))
                percentage,word=call_GRU_predict.GRU_predict(content)
                if(((percentage<maximum)and (percentage>minimum))) and (len(word)>6):
                    date_list.append(dd)
                    content_list.append(content)
                    grade_list.append(grade)
                    company_list.append(company)
                else:
                    continue
    grade_Series=pd.Series(grade_list)
    date_Series=pd.Series(date_list)
    content_Series=pd.Series(content_list)
    #
    company_Series=pd.Series(company_list)
    data_frame=pd.DataFrame()
    data_frame['company']=company_Series
    data_frame['date']=date_Series
    data_frame['grade']=grade_Series
    data_frame['content']=content_Series
    #
    good_data=data_frame[data_frame['grade']>2]
    bad_data=data_frame[data_frame['grade']<3]
    if not os.path.exists('C:\\Data\\thisweek_classified.csv'):
        data_frame.to_csv('C:\\Data\\thisweek_selected_classified.csv',index=False, mode='w',encoding='utf_8_sig')
    else:
        data_frame.to_csv('C:\\Data\\thisweek_selected_classified.csv',index=False,mode='a',encoding='utf_8_sig',header=False)
    
    writer=pd.ExcelWriter('C:/data/thisweek_selected_classified.xlsx')
    if not os.path.exists(writer):
        good_data.to_excel(writer,sheet_name='good',header=True)
        bad_data.to_excel(writer,sheet_name='bad',header=True)
    else:
        good_data.to_excel(writer,sheet_name='good',header=False)
        bad_data.to_excel(writer,sheet_name='bad',header=False)
    writer.save()
    return data_frame
    
    
def classified_selected_data():
    url,company=call_url.select_url()
    load=call_all_company.weekly_selected_classified_data(url,company)
    return load

 

 

4. 감성분류를 통해 분류되지 않은 선택된 회사 데이터

def weekly_selected_unclassified_data(url,company):
    start_date,end_date=start_to_date(),end_to_date()
    driver = webdriver.Chrome('C:\\Users\\LeeKwanHyeong\\chromedriver_win32\\chromedriver.exe',chrome_options=options)
    driver.implicitly_wait(2)
    driver.get(url)
     # sort 선택창
    elem = driver.find_element_by_xpath("//span[@class='DPvwYc']")
    elem.click()
    time.sleep(3)
    pyautogui.press('up')
    time.sleep(0.7)
    pyautogui.press('up')
    time.sleep(0.7)
    pyautogui.press('enter')
    
        
    while(True):
        driver.execute_script("window.scrollTo([0],document.body.scrollHeight);")
        time.sleep(0.5)
        try:
            element=driver.find_element_by_xpath('//div[@class="U26fgb O0WRkf oG5Srb C0oVfc n9lfJ"]')
            if(element is not None):
                element.click()
                break
        except Exception:
            continue
    html=driver.page_source
    driver.quit()
    bsObj=BeautifulSoup(html,'lxml')
    div_reviews=bsObj.find_all("div",{"class":"d15Mdf bAhLNe"})
    
    
    
    #
    company_list,grade_list,date_list,content_list=[],[],[],[]
    
    for div in div_reviews:
        date_=div.find('span',{"class":"p2TkOb"}).get_text()
        t=re.findall(r"\d*\.\d+|\d+",date_)
        date='{0}-{1}-{2}'.format(t[0],t[1],t[2])
        year, month, day=int(t[0]), int(t[1]), int(t[2])
        dd=datetime(year,month,day)
        if((dd-start_date>=timedelta(days=0)) and (end_date-dd>=timedelta(days=0))):
                content=div.find('span',{'jsname':'bN97Pc'}).get_text()
                content=content.replace("전체 리뷰",'')
                content=re.sub('[^가-힣0-9a-zA-Z_!?@#%^&-=:;,\"\'<>\\s]','',content)
                content.encode('utf-8')
                grade=len(div.find_all('div',{'class':'vQHuPe bUWb7c'}))
                percentage,word=call_GRU_predict.GRU_predict(content)
               
                date_list.append(dd)
                content_list.append(content)
                grade_list.append(grade)
                company_list.append(company)
    grade_Series=pd.Series(grade_list)
    date_Series=pd.Series(date_list)
    content_Series=pd.Series(content_list)
    #
    company_Series=pd.Series(company_list)
    data_frame=pd.DataFrame()
    data_frame['company']=company_Series
    data_frame['date']=date_Series
    data_frame['grade']=grade_Series
    data_frame['content']=content_Series
    #
    good_data=data_frame[data_frame['grade']>2]
    bad_data=data_frame[data_frame['grade']>3]
    
    writer=pd.ExcelWriter("C:/data/thisweek_selected_unclassified.xlsx")
    if not os.path.exists(writer):
        good_data.to_excel(writer,sheet_name='good',header=True)
        bad_data.to_excel(writer,sheet_name='bad',header=True)
    else:
        good_data.to_excel(writer,sheet_name='good',header=False)
        bad_data.to_excel(writer,sheet_name='bad',header=False)
    writer.save()
    if not os.path.exists('C:\\Data\\thisweek_selected_unclassified.csv'):
        data_frame.to_csv('C:\\Data\\thisweek_selected_unclassified.csv',index=False, mode='w',encoding='utf_8_sig')
    else:
        data_frame.to_csv('C:\\Data\\thisweek_selected_unclassified.csv',index=False,mode='a',encoding='utf_8_sig',header=False)
    
    
    return data_frame
    
    
    
    
def none_classified_selected_data():
    url,company=call_url.select_url()
    load=call_all_campany.weekly_selected_classified_data(url,company)
    return load

 

 

 

사실 준비하는데 가장 많이 공을 들인 부분이다. 훈련된 단어들을 통해 어떻게 관련지어 워드클라우드로 표현할까이다.

본인이 행한 기법은 only 긍정 단어, only 부정 단어, 긍정&부정 단어 들로 구분시켜 전체 단어의 갯수, 각 부분별 전체 빈도수, 각 단어의 빈도수를 구하여 조합을 시킨 스코어값을 대입했다.

그렇게 되면 새로운 데이터와 비교하였을때 훈련시킨 데이터의 가중치를 통해 중요도를 구분할 수 있기 때문이다. 위 계산과정은 생략하겠다. 

 

def call_dict():
    read_ne_df=pd.read_pickle("C:\\data\\real_ne.pkl")
    read_po_df=pd.read_pickle("C:\\data\\real_po.pkl")
    read_with_df=pd.read_pickle("C:\\data\\real_with.pkl")
    po_word=list(np.array(read_po_df['word']))
    po_weight=list(np.array(read_po_df['weight']))
    ne_word=list(np.array(read_ne_df['word']))
    ne_weight=list(np.array(read_ne_df['weight']))
    with_word=list(np.array(read_with_df['word']))
    with_weight=list(np.array(read_with_df['weight']))
    all_word=po_word+ne_word+with_word
    all_weight=po_weight+ne_weight+with_weight
    all_list=[all_word,all_weight]
    all_dic=dict(zip(*all_list))
    return all_dic

#들어오는 리뷰들을 지정된 점수로 분류하여 라인별로 묶기.
#들어오는 리뷰들을 지정된 점수로 분류하여 라인별로 묶기.
def scoring(sentence):
    score,word,weight=[],[],[]
    a,b=[],[]
    dictionary=call_dict()
    summation=0
    stopwords =['도', '는', '다', '의', '가', '이', '은',  '한', '에', '하', '고', '을', '를', '인', '듯', '과', '와', '네', '들', '듯', '지', '임', '게','요','거','로','으로',
            '것','수','할','하는','제','에서','그','데','번','해도','죠','된','건','바','구','세','최신','.']
    word_tokens=okt.morphs(sentence)
    word_tokens=[x for x in word_tokens if x not in stopwords]
    
    for x in word_tokens:
        if dictionary.get(x):
            
            
            if(len(x)==1):
                continue
            elif(len(x)>1):
                word.append(x)
                score.append(dictionary[x])
        else:
            continue
    for sc in score:
        summation+=sc
    for sc in score:
        weight.append(sc/summation)
    all_list=[word,weight]
    dict_n=dict(zip(*all_list))
    s_dic=sorted(dict_n.items(),key=lambda x:x[1],reverse=True)
    best_dic=s_dic[:10]
    temp_word,temp_weight=[],[]
    for split in range(len(best_dic)):
        list_=list(best_dic[split])
        temp_word.append(list_[0])
        temp_weight.append(list_[1])
    final_list=[temp_word,temp_weight]
    final=dict(zip(*final_list))
        
    return final
## scoring function을 이용해 csv로 받아온 리뷰를 정렬 
##location 매개변수는 메인함수에서 돌릴때 찾아서 변경
def merge_all(data):
    #데이터프레임으로 된것 저장
    merged={}
    temp_list=[]
    for line in data['content']:
        x=scoring(line)
        temp_list.append(x)
    for mer in range(len(temp_list)):
        merged={**temp_list[mer],**merged}
    return merged

def wordcloud(df):
    tokens=merge_all(df)
    wordcloud=WordCloud(font_path='C:/Windows/Fonts/malgun.ttf',background_color='white',colormap='Accent_r',
                       width=1500,height=1000).generate_from_frequencies(tokens)
    plt.imshow(wordcloud)
    plt.axis('off')

    plt.show()

 

이메일 기능도 요구하셨으니 이메일 기능도 만들어보자

 

#sendmail.py
import os
import smtplib
 
from email import encoders
from email.utils import formataddr
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

 
class undeadkwandoll(object):
    ENCODING = 'UTF-8'
 
    host = None
    port = None
    from_addr = None
    to_addrs = None
    message = None
    
    debug = False
    _isLogin = False
    _existAttachments = False
 
    def __init__(self, address:tuple, from_addr:str, to_addrs:list, debug=False, **kwargs):
        self.host, self.port = address
        self.from_addr = from_addr
        self.to_addrs = to_addrs
        
        # 인증 계정
        if kwargs.get("username") is not None:
            self.setAuth(
                kwargs.get("username")
                , kwargs.get("password")
            )
        
        # 디버그 모드
        self.debug = debug is not False
    
        # 첨부파일로 전송 불가능한 확장자
        self.blocked_extensions = (
            ".ade", ".adp", ".apk", ".appx", ".appxbundle", ".bat"
            , ".cab", ".chm", ".cmd", ".com", ".cpl", ".dll", ".dmg"
            , ".exe", ".hta", ".ins", ".isp", ".iso", ".jar", ".js"
            , ".jse", ".lib", ".lnk", ".mde", ".msc", ".msi", ".msix"
            , ".msixbundle", ".msp", ".mst", ".nsh", ".pif", ".ps1"
            , ".scr", ".sct", ".shb", ".sys", ".vb", ".vbe", ".vbs"
            , ".vxd", ".wsc", ".wsf", ".wsh"
        )
 
    def setAuth(self, username, password):
        self._isLogin = True
        self.username = username
        self.password = password
 
    def setMail(self, subject, body, body_type='plain', attachments=None):
        '''
        Content-Type:
            - multipart/alternative: 평문 텍스트와 HTML과 같이 다른 포맷을 함께 보낸 메시지 
            - multipart/mixed: 첨부파일이 포함된 메시지
 
        REF:
            - https://ko.wikipedia.org/wiki/MIME#Content-Type
        '''
        # 첨부파일 여부
        self._existAttachments = attachments is not None
        self.content_sub_type = "mixed" if self._existAttachments else "alternative"
 
        # 메일 콘텐츠 설정
        self.message = MIMEMultipart( self.content_sub_type )
 
        # 받는 사람 주소 설정. [( 이름 <이메일> )]
        self.FROM_ADDR_FMT = formataddr( self.from_addr )
        self.TO_ADDRS_FMT = ",".join([ formataddr( addr ) for addr in self.to_addrs ])
        
        # 메일 헤더 설정
        self.message.set_charset( self.ENCODING )
        self.message['From'] = self.FROM_ADDR_FMT
        self.message['To'] = self.TO_ADDRS_FMT
        self.message['Subject'] = subject
        
        # 메일 콘텐츠 - 내용
        self.message.attach(MIMEText( body, body_type, self.ENCODING ))
 
        # 메일 콘텐츠 - 첨부파일
        if self._existAttachments:
            self._attach_files( attachments )
 
        return self
    
    def _attach_files(self, attachments):
        '''
        Content-disposition:
            - 파일명 지정
        MIME type:
            - application/octect-stream: Binary Data
        REF:
            - https://www.freeformatter.com/mime-types-list.html
        '''
 
        for attachment in attachments:
            attach_binary = MIMEBase("application", "octect-stream")
            try:
                binary = open(attachment, "rb").read() # read file to bytes
 
                attach_binary.set_payload( binary )
                encoders.encode_base64( attach_binary ) # Content-Transfer-Encoding: base64
                
                filename = os.path.basename( attachment )
                attach_binary.add_header("Content-Disposition", 'attachment', filename=(self.ENCODING, '', filename))
                
                self.message.attach( attach_binary )
            except Exception as e:
                print( e )
 
    def send(self):
        session = None
        try:
            # 메일 세션 생성
            session = smtplib.SMTP( self.host, self.port )
            session.set_debuglevel( self.debug )
            session.ehlo()
 
            # SMTP 서버 계정 인증
            if self._isLogin:
                session.starttls()
                session.login(self.username, self.password)
            
            # 메일 발송
            session.sendmail(self.FROM_ADDR_FMT, self.TO_ADDRS_FMT, self.message.as_string())
            print( 'Successfully sent the mail!!!' )
            
        except Exception as e:
            print( e )
        finally:
            if session is not None:
                session.quit()
 
 
 

 

위 클래스는 오픈소스를 활용하였다.

 

각 부분별로 함수를 만들어보자.

def sending_classified_all_data():
    # SMTP 서버 정보
    smtp_address = ( 'smtp.gmail.com', 587 )        # SMTP 서버 호스트, 포트


    # SMTP 계정 정보
    username = "#";                 # Gmail 계정
    password = "#";                   # Gmail 앱 비밀번호
    from_addr = ('#', '#')
    
    "이름을 적으세요"
    to_addrs=[(input("이름을 적으세요"),input("보낼 이메일 주소를 적으세요: "))]
    
    subject="분류된 리뷰 이메일입니다."
    body='''  '''
    attachments = [os.path.join('C:\data','thisweek_classified.xlsx')]
    
    mail=undeadkwandoll(smtp_address,from_addr,to_addrs,debug=False)
    
    mail.setAuth(username,password)
    mail.setMail(subject,body,'html',attachments=attachments)
    mail.send()

#으로 처리한 부분은 이미 적혀있는 것이다. 

def sending_unclassified_all_data():
    # SMTP 서버 정보
    smtp_address = ( 'smtp.gmail.com', 587 )        # SMTP 서버 호스트, 포트


    # SMTP 계정 정보
    username = "#";                 # Gmail 계정
    password = "#";                   # Gmail 앱 비밀번호
    from_addr = ('Google', '#')
    
    "이름을 적으세요"
    to_addrs=[(input("이름을 적으세요"),input("보낼 이메일 주소를 적으세요: "))]
    
    subject="분류된 리뷰 이메일입니다."
    body='''  '''
    attachments = [os.path.join('C:\data','thisweek_unclassified.xlsx')]
    
    mail=undeadkwandoll(smtp_address,from_addr,to_addrs,debug=False)
    
    mail.setAuth(username,password)
    mail.setMail(subject,body,'html',attachments=attachments)
    mail.send()
    
def sending_classified_selected_data():
    # SMTP 서버 정보
    smtp_address = ( 'smtp.gmail.com', 587 )        # SMTP 서버 호스트, 포트


    # SMTP 계정 정보
    username = "#";                 # Gmail 계정
    password = "#";                   # Gmail 앱 비밀번호
    from_addr = ('Google', '#')
    
    "이름을 적으세요"
    to_addrs=[(input("이름을 적으세요"),input("보낼 이메일 주소를 적으세요: "))]
    
    subject="분류된 리뷰 이메일입니다."
    body='''  '''
    attachments = [os.path.join('C:\data','thisweek_selected_classified.xlsx')]
    
    mail=undeadkwandoll(smtp_address,from_addr,to_addrs,debug=False)
    
    mail.setAuth(username,password)
    mail.setMail(subject,body,'html',attachments=attachments)
    mail.send()
    
def sending_unclassified_all_data():
    # SMTP 서버 정보
    smtp_address = ( 'smtp.gmail.com', 587 )        # SMTP 서버 호스트, 포트


    # SMTP 계정 정보
    username = "#";                 # Gmail 계정
    password = "#";                   # Gmail 앱 비밀번호
    from_addr = ('Google', '#')
    
    "이름을 적으세요"
    to_addrs=[(input("이름을 적으세요"),input("보낼 이메일 주소를 적으세요: "))]
    
    subject="분류된 리뷰 이메일입니다."
    body='''  '''
    attachments = [os.path.join('C:\data','thisweek_unclassified.xlsx')]
    
    mail=undeadkwandoll(smtp_address,from_addr,to_addrs,debug=False)
    
    mail.setAuth(username,password)
    mail.setMail(subject,body,'html',attachments=attachments)
    mail.send()
    
def sending_unclassified_selected_data():
    # SMTP 서버 정보
    smtp_address = ( 'smtp.gmail.com', 587 )        # SMTP 서버 호스트, 포트


    # SMTP 계정 정보
    username = "#";                 # Gmail 계정
    password = "#";                   # Gmail 앱 비밀번호
    from_addr = ('Google', '#')
    
    "이름을 적으세요"
    to_addrs=[(input("이름을 적으세요"),input("보낼 이메일 주소를 적으세요: "))]
    
    subject="분류된 리뷰 이메일입니다."
    body='''  '''
    attachments = [os.path.join('C:\data','thisweek_selected_unclassified.xlsx')]
    
    mail=undeadkwandoll(smtp_address,from_addr,to_addrs,debug=False)
    
    mail.setAuth(username,password)
    mail.setMail(subject,body,'html',attachments=attachments)
    mail.send()

 

이메일에 대한 함수도 정리가 끝났다. 마지막 사전준비인 그래프 처리도 시행하자.

이 메인 엔진을 갖고 어떤걸 만들어 볼까 고민을 많이했다. 그래서 사수분께 여쭤봤고 기능들을 받았다.

1. 분류 및 미분류, 회사 전체 및 선택 회사 리뷰 기능

2. 이메일 전송기능

3. 자동 저장기능

4. 퀄리티value의 최대 최소 지정

 

대략적인 작업 흐름도를 그려보았다.

 

 

우선 날짜 입력 함수를 만들어보자.

<날짜 입력 함수>

def start_to_date():
    start_date_list=[]
    st=input("시작 년도를 적으시오: ")
    start_date_list.append(st)
    st=input("시작 월을 적으시오: ")
    start_date_list.append(st)
    st=input("시작 일을 적으시오: ")
    start_date_list.append(st)
    s_year,s_month,s_day=int(start_date_list[0]), int(start_date_list[1]), int(start_date_list[2])
    start_date=datetime(s_year,s_month,s_day)
    return start_date

def end_to_date():
    
    end_date_list=[]
    et=input("종료 년도를 적으시오: ")
    end_date_list.append(et)
    et=input("종료 월을 적으시오: ")
    end_date_list.append(et)
    et=input("종료 일을 적으시오: ")
    end_date_list.append(et)
    e_year,e_month,e_day=int(end_date_list[0]), int(end_date_list[1]), int(end_date_list[2])    
    end_date=datetime(e_year,e_month,e_day)
    
    return end_date

이 함수를 통해 우리가 반환 받는 값은 start_date(시작일) end_date(종료일) 이다. 이 사이의 리뷰들을 가져오기 위한 함수이다.

 

 

def call_url():
    
    url_dict={'CameraFi':'https://play.google.com/store/apps/details?id=com.vaultmicro.camerafi.live&hl=ko&gl=US&showAllReviews=true',
              'V_app':'https://play.google.com/store/apps/details?id=com.naver.vapp&hl=ko&gl=US&showAllReviews=true',
              'Mobizen':'https://play.google.com/store/apps/details?id=com.rsupport.mobizen.live&hl=ko&gl=US&showAllReviews=true',
              'Bigolive':'https://play.google.com/store/apps/details?id=sg.bigo.live&hl=ko&gl=US&showAllReviews=true',
              'Omlet':'https://play.google.com/store/apps/details?id=mobisocial.arcade&hl=ko&gl=US&showAllReviews=true',
              'Sgether':'https://play.google.com/store/apps/details?id=com.sgrsoft.streetgamer&hl=ko&gl=US&showAllReviews=true'}
    return url_dict    

call_url함수는 전체 회사 데이터를 가져오기 위한 사전 url 세팅 함수이다.

혹여, 나중에 더 많은 url이 필요하다면 txt에 저장해 한줄씩 읽어오는 방법도 물론 있다.

 

def select_url():
    url_list=['https://play.google.com/store/apps/details?id=com.vaultmicro.camerafi.live&hl=ko&gl=US&showAllReviews=true',
              'https://play.google.com/store/apps/details?id=com.naver.vapp&hl=ko&gl=US&showAllReviews=true',
              'https://play.google.com/store/apps/details?id=com.rsupport.mobizen.live&hl=ko&gl=US&showAllReviews=true',
              'https://play.google.com/store/apps/details?id=sg.bigo.live&hl=ko&gl=US&showAllReviews=true',
              'https://play.google.com/store/apps/details?id=mobisocial.arcade&hl=ko&gl=US&showAllReviews=true',
              'https://play.google.com/store/apps/details?id=com.sgrsoft.streetgamer&hl=ko&gl=US&showAllReviews=true']
    
    check_num=int(input("원하는 회사를 고르시오: \n"+"[0]:CameraFi\n"+"[1]:V_App\n"+"[2]:BigoLive\n"+"[3]:Mobizen\n"+"[4]:Omlet\n"+"[5]:Sgether\n"))
    
    name=check_num
    if(name==0):
        CameraFi_live=url_list[0]
        checking_url=[CameraFi_live,'CameraFi']
        checked=checking_url[0],checking_url[1]
            
    elif(name==1):
        V_App=url_list[1]
        checking_url=[V_App,'V_App']
        checked=checking_url[0],checking_url[1]
            
    elif(name==2):
        Mobizen=url_list[2]
        checking_url=[Mobizen,'Mobizen']
        checked=checking_url[0],checking_url[1]
            
    elif(name==3):
        Bigolive=url_list[3]
        checking_url=[Bigolive,'Bigolive']
        checked=checking_url[0],checking_url[1]
            
    elif(name==4):
        Omlet=url_list[4]
        checking_url=[Omlet,'Omlet']
        checked=checking_url[0],checking_url[1]
    elif(name==5):
        Sgether=url_list[5]
        checking_url=[Sgether,'Sgether']
        checked=checking_url[0],checking_url[1]
    return checked

select_url함수는 선택적 회사 데이터를 가져오기 위한 사전 url 세팅 함수이다. 

def GRU_predict(new_sentence):
    max_len=90
    new_sentence=okt.morphs(new_sentence)
    new_words=[word for word in new_sentence if not word in stopwords]
    encoded=tokenizer.texts_to_sequences([new_sentence])
    pad_new=pad_sequences(encoded,maxlen=max_len)
    score=float(GRU_model.predict(pad_new))
    percentage=score*100
    return percentage,new_words

앞서 만들어본 GRU모델은 이미 h5 파일로 저장되어있다. 그러므로 이걸 불러서 사용하기만 하면 된다.

 

 

이메일 전송기능도 준비하자.

titanic_data.iloc[0][3]

'Braund, Mr. Owen Harris'

데이터는 Titanic 데이터를 확인해보자.

titanic_data=pd.read_csv("C:/data/titanic/train.csv")
titanic_data

이런식으로 나오는 형태가 데이터프레임이다. 칼럼 즉 변수는 총 12개가 있다. 초심자라고 부담스러워 하지마라. 곧 할것이다.

실제 데이터를 다루기 시작할 때 가장 많이 사용하는 것이 특정 칼럼(변수) 혹은 특정열을 선택해서 아니면 각각의 범위를 지정해서 보는것이다. 실제 Pandas에서 제공해 주는 함수에는 정말 많은 것이 있지만, 대표적인 것만 설명하겠다. 

 

iloc

titanic_data.iloc[0]

위 전체 데이터와 비교해보자. 0번째 인덱스에 있는 value들을 전부 가져온다.

-특정 변수에서 필요한 인덱스 값을 갖고 와보자.

titanic_data.iloc[0][3]

'Braund, Mr. Owen Harris'

titanic_data.iloc[0]['Name']

'Braund, Mr. Owen Harris'

iloc이란 행이든 열이든 숫자로 location을 나타내서 Selecting or indexing 하는 방법이다. 그러나 변수 명을 집어넣어도 상관없다.

해석해보자. 행렬로 설명한다. iloc[행][열] 방식이다. 즉,

나는 [0]번째 전체 행에서 [3] 번째 행을 선택해 보고싶다.

나는 [0]번째 전체 행에서 ['Name']변수에 위치한 값을 선택해 보고싶다.

같은 의미이다.

 

정확한 표현 방식 및 정리는 다음과 같다.

 

titanic.iloc[1] # titanic 1번째 인덱스의 행 선택 추출
titanic.iloc[-1] # titanic 마지막 인덱스의 행 선택 추출
titanic.iloc[:,1] # titanic 1번째 인덱스의 열 선택 추출
titanic.iloc[:,-1] # titanic 마지막 인덱스의 열 선택 추출



titanic.iloc[0:5] # 0번째부터 5번째 인덱스 행 선택 추출
titanic.iloc[:,0:5] #0번째부터 5번째 열까지 선택 추출


titanic.iloc[[0,5,24],[1,4,7]] # 0,5,24 인덱스의 행과 1,4,7인덱스의 행 선택 추출

 

주의할점. 

-어떤 방식으로 내가 행과 열을 selection&extraction 하느냐에 따라 그 output structure은  데이터프레임이 될 수 있고 시리즈 형식이 될 수 있다.

-또한 인덱스라는 의미로 주석표기한 이유는 기본 파이썬 언어 인덱스는 0부터이다. 번째로 주석표기한다면 index+1을 해야하기에 혼동을 야기할 수 있으므로 인덱스로 표기한다.

 

iloc은 요즘 잘 사용하지 않는다고 한다. 하지만 코딩을 활용한 분석에서의 코딩은 내가 원하는 방식으로 이끌어가도 괜찮다고 생각한다.

 

'Data analysis > Pandas' 카테고리의 다른 글

pandas.DataFrame.apply  (0) 2021.03.16
[Pandas] DataFrame  (0) 2021.01.15
[Pandas] Series  (0) 2021.01.15
[Pandas] DataFrame(개념)  (0) 2021.01.13

Pandas 데이터 분석을 시작하려면 무조건, 필수로 import 해야되는 라이브러리. 내가 공부하는게 아니라 누군가를 알려줘야 한다고 생각할때, 과연 어떤 방식으로 쉽게 설명을 해줄까...하다가 우선 데이터프레임을 이해하기 전에 어떤식으로 코딩을 하는지를 먼저 알려주는게 나을 것 같다. 바로 시작해보자.

 

import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt

 

본인은 초심자들을 위한 내용을 제공할 것이기에, 어느정도 숙련도가 있는 분석가들은 과감하게 나가 주길 바란다.

-import [main_library] as [value] 즉, padas라이브러리를 가져올건데 나는 이걸 사용하기 위해 pd로 줄여서 쓸거야 왜냐면 귀찮거든 이라는 의미다. 좀더 추가로 설명하자면 pd를 ks 로 바꿔 설정해도 상관없다.

-근데 왜 이렇게 해야하는가.. 지금 시작할 튜토리얼과 연관성이 있다.

padas.DataFrame(~~)
pd.DataFrame(~~)

호출라이브러리.호출라이브러리기능 순이다. 즉 pandas를 하면 귀찮다! 

 

<다시 본론으로...>

그래서 결국 pandas에서 DataFrame이란 무엇이냐... 통계분석 언어 중 하나인 R이 있다. 온전히 통계 분석을 위해 개발된 R 과는 다르게 python은 일반 프로그램언어이다. 그러므로 데이터 분석을 하기 위해서는 여러가지 라이브러리를 사용할 수 밖에 없는 것이다. 이 패키지들 중 R의 dataframe 데이터 타입을 참고하여 만든 것이 바로 pandas dataframe이다. pandas는 dataframe을 주로 다루기 위한 라이브러리이며, dataframe을 자유롭게 가공하는 것은 데이터 분석가들에게 중요하다. 

우리가 데이터를 다루려면 파이썬 자료구조인 리스트, 튜플, 딕셔너리와 같은 것을 써야하는데 자유자재로 변경 및 처리가 가능하다면, 데이터프레임이 굳이 필요 없을지도..?

 

우리가 데이터 분석을 하게 된다면 직접 데이터를 만들지 않는다. csv 및 excel 등에 저장되어있는 데이터를 받아오는데 요즘 웹 블로그에서는 만드는 것부터 설명을 해준다. 본인은 생략한다.

불러오자

csv_data=pd.read_csv("C:/data/파일이름.csv")
excel_data=pd.read_excel("C:/data/파일이름.xlsx")

*여담으로 경로 찾아줄 때 절대경로에 저장해있으면 파일이름만 적으면 되지만 다른 경로에 저장되어있다면 위치도 적어주자.

*파일경로 적을때 \\ or /  두가지이다. 백슬래시(\) 하나로는 인식을 못하는게 함정이다.

*불러왔으면 이제 어떤식으로 건드려봐야할지는 다음장에 설명하겠다.

 

'Data analysis > Pandas' 카테고리의 다른 글

pandas.DataFrame.apply  (0) 2021.03.16
[Pandas] DataFrame  (0) 2021.01.15
[Pandas] Series  (0) 2021.01.15
[Pandas] DataFrame 특정 칼럼 혹은 인덱스 선택  (0) 2021.01.13

+ Recent posts