# 1. 중앙일보 기사 데이터 스크롤링 def choongang(x, num): from selenium.webdriver.common.keys import Keys from selenium import webdriver from bs4 import BeautifulSoup import urllib import re import time from tqdm.notebook import tqdm
list_url ="https://www.joongang.co.kr/search/news?keyword=" + x driver = webdriver.Chrome("C:\\data\\chromedriver.exe") driver.implicitly_wait(10) driver.get(list_url) for i in range(num): # 더보기 횟수 더보기 = driver.find_element_by_css_selector('a.btn.btn_outline_gray') 더보기.send_keys('\n') # 엔터 time.sleep(3) driver.find_element_by_xpath("//body").send_keys(Keys.PAGE_DOWN) # 페이지 다운 html = driver.page_source soup = BeautifulSoup(html, "html.parser") base = soup.select("h2.headline > a") params=[] # 상세 기사 url을 담을 리스트 for i in base[5:-5]: # 불필요한 상위 5개 하위 5개 제외 params.append(i.get("href")) file = open("c:\\data\\중앙일보_"+ x + ".txt", "w", encoding = "utf-8") cnt = 0 # 본문 앞에 번호 붙이기 for k in tqdm(params): url = urllib.request.Request(k) f = urllib.request.urlopen(url).read().decode("utf-8")
soup = BeautifulSoup(f, "html.parser") for z in soup.find_all("div", class_ ="article_body fs3"): cnt += 1 file.write(str(cnt) + '. ' + re.sub('[\n\r\t]', '', z.text) + '\n\n') file.close() print('\n※ 스크롤링이 완료되었습니다 \'중앙일보_%s.txt\'파일이 생성되었습니다 ※' %x) driver.quit() # 끝나면 브라우저를 닫기 # 2. 네이버 블로그 데이터 스크롤링 def naver_blog(keyword,page_num):
# 모듈 from selenium import webdriver from selenium.webdriver.common.keys import Keys from bs4 import BeautifulSoup from urllib import request as urlreq import time import re from tqdm.notebook import tqdm
# 크롬 드라이버 binary = "C:\\data\\chromedriver.exe"
# 브라우저를 인스턴스화 driver = webdriver.Chrome(binary)
params = [] for i in range(1,page_num+1): url = "https://section.blog.naver.com/Search/Post.naver?pageNo="+str(i)+"&rangeType=ALL&orderBy=sim&keyword="+keyword driver.get(url) time.sleep(1) html = driver.page_source
soup = BeautifulSoup(html,'html.parser') base = soup.select('div.desc > a') for i in base: params.append(i.get('href'))
params2 = list(set(params))
f2 = open("c:\\data\\네이버블로그_"+keyword+".txt","w",encoding = "utf8")
for k in tqdm(params2): driver = webdriver.Chrome(binary) driver.get(k)
element = driver.find_element_by_id("mainFrame") #iframe 태그 엘리먼트 찾기 driver.switch_to.frame(element)
html2 = driver.page_source
soup2 = BeautifulSoup(html2, 'html.parser') try: #닉네임 크롤링 overlays = ".nick" nick = driver.find_element_by_css_selector(overlays) nickname = nick.text nickname = re.sub('[\n\r\t]','',nickname)
#날짜 크롤링 overlays = ".se_publishDate.pcol2" date = driver.find_element_by_css_selector(overlays) datetime = date.text #내용 크롤링 content = soup2.select('div.se-component-content>div>div>p')
f2.write('\n\nurl주소 : '+k) # url 쓰기 f2.write('\n작성날짜: ' + datetime) # 날짜쓰기 f2.write('\n블로그 작성자['+nickname +']\n') # 닉네임 쓰기 for i in content: if len(i.text) > 1: f2.write(re.sub('[\n\r\t]','',i.text)+'\n') # 내용 크롤링하면서 쓰기 except: continue f2.close() print('\n※ 스크롤링이 완료되었습니다 \'네이버블로그_%s.txt\'파일이 생성되었습니다 ※' %keyword) driver.quit()
# 3. 긍정, 부정 감성분석 def textdata(keyword, num): from tqdm.notebook import tqdm
#1. 텍스트 파일 3개를 불러옵니다. blog = open('C:\\data\\' + keyword + '.txt', encoding='utf-8-sig') positive = open('C:\\data\\pos_pol_word.txt',encoding='utf-8-sig') negative = open('C:\\data\\neg_pol_word.txt',encoding='utf-8-sig')
#2. 텍스트 파일 3개를 읽어들입니다. blog1 = blog.read() # 게시글을 문자형 변수 blog1 에 담는다. pos = set(positive.read().split('\n')) # 긍정단어를 엔터로 구분해서 리스트로 구성 neg = set(negative.read().split('\n')) # 부정단어를 엔터로 구분해서 리스트로 구성
#3. pos 와 neg 리스트에서 결측치를 제거합니다. pos = list(filter(lambda x:x,pos)) pos1=set(pos) #중복되는 pos 의 단어를 제거 neg = list(filter(lambda x:x,neg))
# 단어 한 자리는 삭제 pos1 = list(filter(lambda x:len(x) != 1, pos)) neg = list(filter(lambda x:len(x) != 1, neg))
#4. 긍정단어를 갯수와 함께 keyword_pos 에 저장합니다. f2 = open("c:\\data\\" + keyword + "_pos.csv", "w", encoding="utf-8-sig")
for i in tqdm(pos1): # 긍정 단어들을 하나씩 불러와서 i 변수 담습니다. if i in blog1: # blog1 라는 문자열 변수 안에 i 변수의 있는 긍정단어가 포함되어 있다면 f2.write( i + ',' + str(blog1.count(i)) + '\n')
#4. 부정단어를 갯수와 함께 keyword_neg.csv 에 저장합니다. f3= open("c:\\data\\" + keyword + "_neg.csv", "w", encoding="utf-8-sig")
for i in tqdm(neg): # 부정 단어들을 하나씩 불러와서 i 변수 담습니다. if i in blog1: # blog1 라는 문자열 변수 안에 i 변수의 있는 부정단어가 포함되어 있다면 f3.write( i + ',' + str(blog1.count(i)) + '\n')
f2.close() print('※ %s_pos.csv 파일이 생성되었습니다 ※\n' %keyword) f3.close() print('※ %s_neg.csv 파일이 생성되었습니다 ※\n' %keyword) #5. 긍정단어 상위 num개 나열
import pandas as pd pd.set_option('display.max_rows', None) # 생략없이 전부 보기
blog_pos = pd.read_csv("c:\\data\\" + keyword + "_pos.csv" , header=None) blog_pos.columns=['word', 'cnt'] blog_pos['순위']=blog_pos['cnt'].rank(method='dense', ascending=False).astype('int')
print('▶ %s에서 나타난 긍정단어 리스트 상위 %d개\n' %(keyword, num))
a = blog_pos[:].sort_values(by=['순위']).head(num) #head()를 이용 상위 num개만 출력 print(a) #6. 부정 단어 상위 num개 나열
blog_neg = pd.read_csv("c:\\data\\" + keyword + "_neg.csv" , header=None) blog_neg.columns=['word', 'cnt'] blog_neg['순위']=blog_neg['cnt'].rank(method='dense', ascending=False).astype('int') print('\n▶ %s에서 나타난 부정단어 리스트 상위 %d개\n' %(keyword, num))
b = blog_neg[:].sort_values(by=['순위']).head(num) #head()를 이용 상위 num개만 출력 print(b) # 함수 목록 선택 def my_data(): # 목록 선택 datalist = ['중앙일보 기사 데이터 스크롤링', '네이버 블로그 데이터 스크롤링', '긍정, 부정 감성분석'] print('='*21, 'LIST', '='*21) print('\n1. %s\n2. %s\n3. %s\n4. 프로그램 종료\n' %(datalist[0], datalist[1], datalist[2])) print('='*48) while True: num = int(input('\n▶ 번호를 선택하세요 : ')) if num in [1, 2, 3]: print('\'%s\'을 선택하셨습니다\n' %(datalist[num-1])) if num == 1: keyword = input('▶ 키워드를 입력하세요 : ') page = int(input('▶ 더보기를 몇 번 누를까요? : '))
choongang(keyword, page) continue
elif num == 2: keyword2 = input('▶ 키워드를 입력하세요 : ') page2 = int(input('▶ 몇 페이지를 가져올까요? (페이지당 게시글수 7개) : '))
naver_blog(keyword2,page2) continue
elif num == 3: keyword3 = input('▶ 텍스트 파일명을 입력하세요 : ') head_num = int(input('▶ 긍정단어와 부정단어는 상위 몇 개까지 가져올까요? : '))
textdata(keyword3, head_num) continue elif num == 4: print('\n※ 프로그램을 종료합니다 ※\n') break my_data() |