김건

불필요한 파일 삭제

No preview for this file type
1 -# Byte-compiled / optimized / DLL files
2 -__pycache__/
3 -*.py[cod]
4 -
5 -# C extensions
6 -*.so
7 -
8 -# Distribution / packaging
9 -.Python
10 -env/
11 -build/
12 -develop-eggs/
13 -dist/
14 -downloads/
15 -eggs/
16 -.eggs/
17 -lib/
18 -lib64/
19 -parts/
20 -sdist/
21 -var/
22 -*.egg-info/
23 -.installed.cfg
24 -*.egg
25 -
26 -# PyInstaller
27 -# Usually these files are written by a python script from a template
28 -# before PyInstaller builds the exe, so as to inject date/other infos into it.
29 -*.manifest
30 -*.spec
31 -
32 -# Installer logs
33 -pip-log.txt
34 -pip-delete-this-directory.txt
35 -
36 -# Unit test / coverage reports
37 -htmlcov/
38 -.tox/
39 -.coverage
40 -.coverage.*
41 -.cache
42 -nosetests.xml
43 -coverage.xml
44 -*,cover
45 -
46 -# Translations
47 -*.mo
48 -*.pot
49 -
50 -# Django stuff:
51 -*.log
52 -
53 -# Sphinx documentation
54 -docs/_build/
55 -
56 -# PyBuilder
57 -target/
1 -The MIT License (MIT)
2 -
3 -Copyright (c) 2015 Egbert Bouman
4 -
5 -Permission is hereby granted, free of charge, to any person obtaining a copy
6 -of this software and associated documentation files (the "Software"), to deal
7 -in the Software without restriction, including without limitation the rights
8 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 -copies of the Software, and to permit persons to whom the Software is
10 -furnished to do so, subject to the following conditions:
11 -
12 -The above copyright notice and this permission notice shall be included in all
13 -copies or substantial portions of the Software.
14 -
15 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 -SOFTWARE.
22 -
1 -# youtube-comment-downloader
2 -Simple script for downloading Youtube comments without using the Youtube API. The output is in line delimited JSON.
3 -
4 -### Dependencies
5 -* Python 2.7+
6 -* requests
7 -* lxml
8 -* cssselect
9 -
10 -The python packages can be installed with
11 -
12 - pip install requests
13 - pip install lxml
14 - pip install cssselect
15 -
16 -### Usage
17 -```
18 -usage: downloader.py [--help] [--youtubeid YOUTUBEID] [--output OUTPUT]
19 -
20 -Download Youtube comments without using the Youtube API
21 -
22 -optional arguments:
23 - --help, -h Show this help message and exit
24 - --youtubeid YOUTUBEID, -y YOUTUBEID
25 - ID of Youtube video for which to download the comments
26 - --output OUTPUT, -o OUTPUT
27 - Output filename (output format is line delimited JSON)
28 -```
1 -#!/usr/bin/env python
2 -
3 -from __future__ import print_function
4 -import sys
5 -import os
6 -import time
7 -import json
8 -import requests
9 -import argparse
10 -import lxml.html
11 -import io
12 -from urllib.parse import urlparse, parse_qs
13 -from lxml.cssselect import CSSSelector
14 -
15 -YOUTUBE_COMMENTS_URL = 'https://www.youtube.com/all_comments?v={youtube_id}'
16 -YOUTUBE_COMMENTS_AJAX_URL = 'https://www.youtube.com/comment_ajax'
17 -
18 -USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'
19 -
20 -
21 -def find_value(html, key, num_chars=2):
22 - pos_begin = html.find(key) + len(key) + num_chars
23 - pos_end = html.find('"', pos_begin)
24 - return html[pos_begin: pos_end]
25 -
26 -
27 -def extract_comments(html):
28 - tree = lxml.html.fromstring(html)
29 - item_sel = CSSSelector('.comment-item')
30 - text_sel = CSSSelector('.comment-text-content')
31 - time_sel = CSSSelector('.time')
32 - author_sel = CSSSelector('.user-name')
33 -
34 - for item in item_sel(tree):
35 - yield {'cid': item.get('data-cid'),
36 - 'text': text_sel(item)[0].text_content(),
37 - 'time': time_sel(item)[0].text_content().strip(),
38 - 'author': author_sel(item)[0].text_content()}
39 -
40 -
41 -def extract_reply_cids(html):
42 - tree = lxml.html.fromstring(html)
43 - sel = CSSSelector('.comment-replies-header > .load-comments')
44 - return [i.get('data-cid') for i in sel(tree)]
45 -
46 -
47 -def ajax_request(session, url, params, data, retries=10, sleep=20):
48 - for _ in range(retries):
49 - response = session.post(url, params=params, data=data)
50 - if response.status_code == 200:
51 - response_dict = json.loads(response.text)
52 - return response_dict.get('page_token', None), response_dict['html_content']
53 - else:
54 - time.sleep(sleep)
55 -
56 -
57 -def download_comments(youtube_id, sleep=1):
58 - session = requests.Session()
59 - session.headers['User-Agent'] = USER_AGENT
60 - # Get Youtube page with initial comments
61 - response = session.get(YOUTUBE_COMMENTS_URL.format(youtube_id=youtube_id))
62 - html = response.text
63 - reply_cids = extract_reply_cids(html)
64 -
65 - ret_cids = []
66 - for comment in extract_comments(html):
67 - ret_cids.append(comment['cid'])
68 - yield comment
69 - page_token = find_value(html, 'data-token')
70 - session_token = find_value(html, 'XSRF_TOKEN', 4)
71 - first_iteration = True
72 -
73 - # Get remaining comments (the same as pressing the 'Show more' button)
74 - while page_token:
75 - data = {'video_id': youtube_id,
76 - 'session_token': session_token}
77 -
78 - params = {'action_load_comments': 1,
79 - 'order_by_time': True,
80 - 'filter': youtube_id}
81 -
82 - if first_iteration:
83 - params['order_menu'] = True
84 - else:
85 - data['page_token'] = page_token
86 -
87 - response = ajax_request(session, YOUTUBE_COMMENTS_AJAX_URL, params, data)
88 - if not response:
89 - break
90 -
91 - page_token, html = response
92 -
93 - reply_cids += extract_reply_cids(html)
94 - for comment in extract_comments(html):
95 - if comment['cid'] not in ret_cids:
96 - ret_cids.append(comment['cid'])
97 - yield comment
98 -
99 - first_iteration = False
100 - time.sleep(sleep)
101 - # Get replies (the same as pressing the 'View all X replies' link)
102 - for cid in reply_cids:
103 - data = {'comment_id': cid,
104 - 'video_id': youtube_id,
105 - 'can_reply': 1,
106 - 'session_token': session_token}
107 - params = {'action_load_replies': 1,
108 - 'order_by_time': True,
109 - 'filter': youtube_id,
110 - 'tab': 'inbox'}
111 - response = ajax_request(session, YOUTUBE_COMMENTS_AJAX_URL, params, data)
112 - if not response:
113 - break
114 -
115 - _, html = response
116 -
117 - for comment in extract_comments(html):
118 - if comment['cid'] not in ret_cids:
119 - ret_cids.append(comment['cid'])
120 - yield comment
121 - time.sleep(sleep)
122 -
123 -## input video 값 parsing
124 -def video_id(value):
125 - query = urlparse(value)
126 - if query.hostname == 'youtu.be':
127 - return query.path[1:]
128 - if query.hostname in ('www.youtube.com', 'youtube.com'):
129 - if query.path == '/watch':
130 - p = parse_qs(query.query)
131 - return p['v'][0]
132 - if query.path[:7] == '/embed/':
133 - return query.path.split('/')[2]
134 - if query.path[:3] == '/v/':
135 - return query.path.split('/')[2]
136 - # fail?
137 - return None
138 -
139 -
140 -def main():
141 -
142 - #parser = argparse.ArgumentParser(add_help=False, description=('Download Youtube comments without using the Youtube API'))
143 - #parser.add_argument('--help', '-h', action='help', default=argparse.SUPPRESS, help='Show this help message and exit')
144 - #parser.add_argument('--youtubeid', '-y', help='ID of Youtube video for which to download the comments')
145 - #parser.add_argument('--output', '-o', help='Output filename (output format is line delimited JSON)')
146 - #parser.add_argument('--limit', '-l', type=int, help='Limit the number of comments')
147 - Youtube_id1 = input('Youtube_ID 입력 :')
148 - ## Cutting Link를 받고 id만 딸 수 있도록
149 - Youtube_id1 = video_id(Youtube_id1)
150 - youtube_id = Youtube_id1
151 - try:
152 - # args = parser.parse_args(argv)
153 -
154 - #youtube_id = args.youtubeid
155 - #output = args.output
156 - #limit = args.limit
157 - result_List = []
158 - ## input 값을 받고 값에 할당
159 -
160 - ## Limit에 빈 값이 들어갈 경우 Default 값으로 100을 넣게 하였음
161 - if not youtube_id :
162 - #parser.print_usage()
163 - #raise ValueError('you need to specify a Youtube ID and an output filename')
164 - raise ValueError('올바른 입력 값을 입력하세요')
165 -
166 - print('Downloading Youtube comments for video:', youtube_id)
167 - Number = input(' 저장 - 0 저장 안함- 1 : ')
168 - if Number == '0' :
169 - Output1 = input('결과를 받을 파일 입력 :')
170 - Limit1 = input('제한 갯수 입력 : ')
171 - if Limit1 == '' :
172 - Limit1 = 100
173 - Limit1 = int(Limit1)
174 - limit = int(Limit1)
175 -
176 - output = Output1
177 - ##### argument로 받지 않고 input으로 받기 위한 것
178 - with io.open(output, 'w', encoding='utf8') as fp:
179 - for comment in download_comments(youtube_id):
180 - comment_json = json.dumps(comment, ensure_ascii=False)
181 - print(comment_json.decode('utf-8') if isinstance(comment_json, bytes) else comment_json, file=fp)
182 - count += 1
183 - sys.stdout.flush()
184 - if limit and count >= limit:
185 - print('Downloaded {} comment(s)\r'.format(count))
186 - print('\nDone!')
187 - break
188 -
189 - else :
190 - count = 0
191 - i = 0
192 - limit = 40
193 - for comment in download_comments(youtube_id):
194 - dic = {}
195 - dic['cid'] = comment['cid']
196 - dic['text'] = comment['text']
197 - dic['time'] = comment['time']
198 - dic['author'] = comment['author']
199 - result_List.append(dic)
200 - count += 1
201 - i += 1
202 - if limit == count :
203 - print(' Comment Thread 생성 완료')
204 - print ('\n\n\n\n\n\n\n')
205 - break
206 - return result_List
207 - #goto_Menu(result_List)
208 -
209 -
210 -
211 - except Exception as e:
212 - print('Error:', str(e))
213 - sys.exit(1)
214 -
215 -
216 -if __name__ == "__main__":
217 - main()
1 -import downloader
2 -from time import sleep
3 -from konlpy.tag import Twitter
4 -from collections import Counter
5 -from matplotlib import rc
6 -import matplotlib.pyplot as plt
7 -from matplotlib import font_manager as fm
8 -import pytagcloud
9 -import operator
10 -def get_tags (Comment_List) :
11 -
12 - okja = []
13 - for temp in Comment_List :
14 - okja.append(temp['text'])
15 - twitter = Twitter()
16 - sentence_tag =[]
17 - for sentence in okja:
18 - morph = twitter.pos(sentence)
19 - sentence_tag.append(morph)
20 - print(morph)
21 - print('-'*30)
22 - print(sentence_tag)
23 - print(len(sentence_tag))
24 - print('\n'*3)
25 -
26 - noun_adj_list = []
27 - for sentence1 in sentence_tag:
28 - for word,tag in sentence1:
29 - if len(word) >=2 and tag == 'Noun':
30 - noun_adj_list.append(word)
31 - counts = Counter(noun_adj_list)
32 - print(' 가장 많이 등장한 10개의 키워드. \n')
33 - print(counts.most_common(10))
34 - tags2 = counts.most_common(10)
35 - taglist = pytagcloud.make_tags(tags2,maxsize=80)
36 - pytagcloud.create_tag_image(taglist,'wordcloud.jpg',size =(900,600),fontname ='Nanum Gothic', rectangular = False)
37 -
38 -def print_result(Comment_List) :
39 - for var in Comment_List :
40 - print(var)
41 - print('******* 검색 완료 *******')
42 - print('\n\n\n')
43 -
44 -def search_by_author(Comment_List,author_name) :
45 - result_List = []
46 -
47 - for var in Comment_List :
48 - if (var['author'] == author_name) :
49 - result_List.append(var)
50 -
51 - return result_List
52 -def search_by_keyword(Comment_List,keyword) :
53 - result_List = []
54 - for var in Comment_List :
55 - print(var['text'])
56 - if ( keyword in var['text']) :
57 - result_List.append(var)
58 -
59 - return result_List
60 -def search_by_time(Comment_List,Time_input) :
61 - result_List = []
62 - for var in Comment_List :
63 - if(var['time'] == Time_input) :
64 - result_List.append(var)
65 - return result_List
66 -
67 -def make_time_chart (Comment_List) :
68 - result_List = []
69 - save_List = []
70 - day_dict = {}
71 - month_dict = {}
72 - year_dict = {}
73 - hour_dict = {}
74 - minute_dict = {}
75 - week_dict = {}
76 - for var in Comment_List :
77 - result_List.append(var['time'])
78 - for i in range(len(result_List)) :
79 - print(result_List[i] + ' ')
80 - print('\n\n\n\n')
81 - temp_List = list(set(result_List))
82 - for i in range(len(temp_List)) :
83 - print(temp_List[i] + ' ')
84 - print('\n\n\n\n')
85 - for i in range (len(temp_List)) :
86 - result_dict = {}
87 - a = result_List.count(temp_List[i])
88 - result_dict[temp_List[i]] = a
89 - save_List.append(result_dict)
90 -
91 - for i in range (len(save_List)):
92 - num = ''
93 - data = 0
94 - for j in save_List[i] :
95 - num = j
96 - for k in save_List[i].values() :
97 - data = k
98 - if num.find('개월') >= 0 :
99 - month_dict[num] = k
100 - elif num.find('일') >= 0 :
101 - day_dict[num] = k
102 - elif num.find('년') >= 0 :
103 - year_dict[num] = k
104 - elif num.find('시간') >= 0 :
105 - hour_dict[num] = k
106 - elif num.find('주') >= 0 :
107 - week_dict[num] = k
108 - elif num.find('분') >= 0 :
109 - minute_dict[num] = k
110 - year_data = sorted(year_dict.items(), key=operator.itemgetter(0))
111 - month_data = sorted(month_dict.items(), key=operator.itemgetter(0))
112 - week_data = sorted(week_dict.items(), key=operator.itemgetter(0))
113 - day_data = sorted(day_dict.items(), key=operator.itemgetter(0))
114 - hour_data = sorted(hour_dict.items(), key=operator.itemgetter(0))
115 - minute_data = sorted(minute_dict.items(), key=operator.itemgetter(0))
116 - #print(month_data)
117 - #print(week_data)
118 - #print(day_data)
119 - make_chart(year_data,month_data,week_data,day_data,hour_data,minute_data)
120 -
121 -def make_chart(year_data,month_data,week_data,day_data,hour_data,minute_data) :
122 - temp_list = [year_data,month_data,week_data,day_data,hour_data,minute_data]
123 - x_list = []
124 - y_list = []
125 - print(temp_list)
126 - for var1 in temp_list :
127 - for var2 in var1 :
128 - if(var2[0].find('년')>=0):
129 - temp1 = var2[0][0] + 'years'
130 - temp2 = int(var2[1])
131 - x_list.append(temp1)
132 - y_list.append(temp2)
133 - elif(var2[0].find('개월')>=0):
134 - temp1 = var2[0][0] + 'months'
135 - temp2 = int(var2[1])
136 - x_list.append(temp1)
137 - y_list.append(temp2)
138 - elif(var2[0].find('주')>=0):
139 - temp1 = var2[0][0] + 'weeks'
140 - temp2 = int(var2[1])
141 - x_list.append(temp1)
142 - y_list.append(temp2)
143 - elif(var2[0].find('일')>=0):
144 - temp1 = var2[0][0] + 'days'
145 - temp2 = int(var2[1])
146 - x_list.append(temp1)
147 - y_list.append(temp2)
148 - elif(var2[0].find('시간')>=0):
149 - temp1 = var2[0][0] + 'hours'
150 - temp2 = int(var2[1])
151 - x_list.append(temp1)
152 - y_list.append(temp2)
153 - else:
154 - temp1 = var2[0][0] + 'minutes'
155 - temp2 = int(var2[1])
156 - x_list.append(temp1)
157 - y_list.append(temp2)
158 - print(x_list)
159 - plt.bar(x_list,y_list,width = 0.5 , color = "blue")
160 - # plt.show() -> 출력
161 - plt.savefig('chart.png',dpi=300)
162 - # plt.savefig('chart.png', dpi=300)
163 -
164 -def call_main ():
165 - print(' Comment Thread 생성중 \n')
166 -
167 - sleep(1)
168 - print(' **************************************************************')
169 - print(' **************************************************************')
170 - print(' **************************************************************')
171 - print(' **************** 생성 완료 정보를 입력하세요. **************** ')
172 - print(' **************************************************************')
173 - print(' **************************************************************')
174 - print(' **************************************************************')
175 - a = downloader.main()
176 -
177 - return a
178 -
179 -if __name__ == "__main__":
180 - CommentList = call_main()
181 - make_time_chart(CommentList)
182 - ##author_results = search_by_author(CommentList,'광고제거기')
183 - ##text_resutls = search_by_keyword(CommentList,'지현')
184 - ##get_tags(CommentList)
185 - ##print_result(author_results)
186 - ##print_result(text_resutls)
1 -requests
2 -beautifulsoup4
3 -lxml
4 -cssselect
5 -### ũѸ
6 -pygame
7 -pytagcloud
8 -### wordcloud
9 -Jpye1
10 -### Ű м
11 -python -m pip install -U matplotlib==3.2.0rc1
1 -1. Data 받아오기
2 - 1) selenuim을 이용하여 웹페이지에서 데이터를 검색
3 - 2) 원하는 URL 입력받는다
4 - 3) headless하게 구현하기 위해 chrome option 적용하여 driver 생성
5 - 4) naverNews는 댓글 영역 하단 부 '더보기'를 지속적으로 눌러줘야하므로
6 - driver의 find_element_by_css_selector함수로 해당 class인
7 - u_cbox_btn_more을 페이지가 끝날 때까지 돌림
8 - 5) 위의 과정에서 얻은 페이지 소스를 beautifulSoup을 이용하여, find_all을 통해 {사용자ID, 댓글, 작성시간}의 데이터를 각각 raw하게 뽑음. (naverNews의 제한적인 특징으로 사용자ID 뒤 4자리는 비공개처리됨)
9 -
10 -2. 사용할 DataSet으로 가공
11 - 1) 리스트 형태로 각각 nicknames(사용자ID), comments(댓글), times(작성시간)을 뽑아냄
12 - 2) 세 리스트에서 짝을 이루는 쌍을 dictionary형태로 {사용자ID, 댓글, 작성시간} 다음과 같이 저장
13 - 3) 저장된 dictionary list(info_dic)을 최종 결과 리스트인 naverNewsList에 저장한다.
14 -
15 -3. 함수 구현
16 - 1) KEYWORD 기반 검색 기능
17 - 2) 가장 자주 나온 단어 검색 기능
18 - 3) ID 기반 검색 기능
19 - 4) 시간 대별 검색 기능
20 - 등 여러 함수 구현 예정
21 -
22 -=> 수정사항
23 -
24 - data를 get하여 정제하는 파일을 모듈로 분리해 내어 list형태로 저장된 데이터셋을 반환하여
25 - main 에서 사용할 수 있도록 한다. 이 후 main에서 리스트를 받아와 url을 입력받아 데이터를
26 - 받아오는 방식으로 사용한다. 이 후, keyword기반, id기반, 시간대 기반 검색 함수를 구현하였고
27 - 시간대별 검색 함수의 기능 보강과 가장 자주 나온 단어 검색 기능을 추가 구현할 예정이다.
28 -
29 -* 4차 수정사항
30 -
31 - 기존파일의 분리 관리 시, import관련 오류 문제 해결 완료(하나의 파일로 관리)
32 - 사용자 UI의 틀을 구축해놓았고, 곧바로 함수별 추가 세부 구현 예정
33 -
34 -* 5차 수정사항
35 -
36 - 1) 네이버 댓글공간엑서 받아온 날짜 정보를 YYYY-MM-DD형식으로 바꿈. ('방금 전, 몇 분 전, 몇 시간 전, 몇 일 전'의 경우를 처리하기 위해 dateTime과 timeDelta 모듈을 활용하여
37 - 현재 날짜를 기준으로 계산하여 YYYY-MM-DD로 저장될 수 있도록
38 - 코드 추가)
39 - 2) 시간대별로 (시작시간, 끝시간)을 입력하여 그 시간에 해당하는 기사를 출력해주는 함수 구현
40 -
41 - 가장 자주 많이 나온 단어 검색과 MATPLOTLIB을 활용한 시각적 표현 구현 예정
42 -
43 -* 6차 수정사항
44 -
45 - konlpy를 활용한 명사 추출 및 단어 빈도수가 많으 순대로 사용자가 입력한 limit만큼 출력해주는 함수 구현 완료
...\ No newline at end of file ...\ No newline at end of file
1 -from selenium import webdriver
2 -from selenium.common import exceptions
3 -from bs4 import BeautifulSoup
4 -from datetime import datetime, timedelta
5 -from konlpy.tag import Twitter
6 -from collections import Counter
7 -import time
8 -
9 -
10 -def getData(url):
11 - ## chrome option걸기 (headless하게 웹 크롤링 수행하기 위해<웹페이지 안보이게 하기>)
12 - options = webdriver.ChromeOptions()
13 - #options.add_argument('headless')
14 - #options.add_argument("disable-gpu")
15 - #_url = "https://entertain.naver.com/ranking/comment/list?oid=144&aid=0000642175" # 크롤링할 URL
16 - _url = url # 크롤링할 URL
17 - webDriver = "C:\\Users\\user\\Desktop\\chromedriver_win32\\chromedriver.exe" # 내 웹드라이버 위치
18 - driver = webdriver.Chrome(webDriver,chrome_options=options)
19 - #driver = webdriver.Chrome(webDriver)
20 - driver.get(_url)
21 - pageCnt = 0
22 - driver.implicitly_wait(3) # 페이지가 다 로드 될때까지 기다리게함
23 - try:
24 - while True: # 댓글 페이지 끝날때까지 돌림
25 - #driver의 find_element_by_css_selector함수로 '네이버 뉴스'의 댓글 '더보기' 버튼을 찾아서 계속 클릭해준다(끝까지)
26 - driver.find_element_by_css_selector(".u_cbox_btn_more").click()
27 - pageCnt = pageCnt+1
28 -
29 - except exceptions.ElementNotVisibleException as e: # 페이지가 끝남
30 - pass
31 -
32 - except Exception as e: # 다른 예외 발생시 확인
33 - print(e)
34 -
35 - pageSource = driver.page_source # 페이지 소스를 따와서
36 - result = BeautifulSoup(pageSource, "lxml") # 빠르게 뽑아오기 위해 lxml 사용
37 -
38 - # nickname, text, time을 raw하게 뽑아온다
39 - comments_raw = result.find_all("span", {"class" : "u_cbox_contents"})
40 - nicknames_raw = result.find_all("span", {"class" : "u_cbox_nick"})
41 - times_raw = result.find_all("span", {"class" : "u_cbox_date"})
42 -
43 - # nickname, text, time 값 만을 뽑아내어 리스트로 정리한다
44 - comments = [comment.text for comment in comments_raw]
45 - nicknames = [nickname.text for nickname in nicknames_raw]
46 - times = [time.text for time in times_raw]
47 -
48 - naverNewsList = []
49 -
50 - for i in range(len(comments)):
51 - info_dic = {'userID' : nicknames[i], 'comment' : comments[i], 'time' : times[i]}
52 - naverNewsList.append(info_dic)
53 -
54 - return naverNewsList
55 - #driver.quit()
56 -
57 -from time import sleep
58 -
59 -def print_cList(c_List) :
60 - for item in c_List :
61 - print(item)
62 -
63 -def search_by_author(c_List,user_ID) :
64 - result_List = []
65 - for item in c_List :
66 - #print(item['userID'])
67 - if ( user_ID in item['userID']) :
68 - result_List.append(item)
69 - return result_List
70 -
71 -def search_by_keyword(c_List,keyword) :
72 - result_List = []
73 - for item in c_List :
74 - #print(item['comment'])
75 - if ( keyword in item['comment']) :
76 - result_List.append(item)
77 - return result_List
78 -
79 -def refine_time(c_List): # 시간에서 몇일 전, 몇 분 전, 방금 전 등의 형태를 YYYY.MM.DD로 바꿔준다
80 - now = datetime.now()
81 -
82 - for item in c_List:
83 - if (item['time'].find('전') != -1): # ~~전이 있으면
84 - if (item['time'].find('일 전') != -1): # ~일 전이라면
85 - _day = -(int)(item['time'][0]) # 몇 일전인지에 대한 정수형 변수
86 - tempTime = now + timedelta(days=_day)
87 - item['time'] = str(tempTime)
88 - item['time'] = item['time'][0:10]
89 - continue
90 - elif (item['time'].find('시간 전') != -1):
91 - _index = item['time'].index('시')
92 - _time = -(int)(item['time'][0:_index]) # 몇 시간 전인지에 대한 정수형 변수
93 - tempTime = now + timedelta(hours = _time)
94 - item['time'] = str(tempTime)
95 - item['time'] = item['time'][0:10]
96 - continue
97 - elif (item['time'].find('분 전') != -1):
98 - _index = item['time'].index('분')
99 - _minute = -(int)(item['time'][0:_index]) # 몇 분 전인지에 대한 정수형 변수
100 - tempTime = now + timedelta(minutes = _minute)
101 - item['time'] = str(tempTime)
102 - item['time'] = item['time'][0:10]
103 - continue
104 - elif (item['time'].find('방금 전') != -1):
105 - tempTime = now
106 - item['time'] = str(tempTime)
107 - item['time'] = item['time'][0:10]
108 - continue
109 - else:
110 - item['time'] = item['time'][0:10]
111 - continue
112 -
113 -
114 -
115 -
116 -
117 -def search_by_time(c_List,startTime, endTime) :
118 - result_List = []
119 -
120 - startYear = int(startTime[0:4])
121 -
122 - if (int(startTime[5]) == 0): # 한자리의 월일 때
123 - startMonth = int(startTime[6])
124 - else:
125 - startMonth = int(startTime[5:7])
126 -
127 - if (int(startTime[8]) == 0): # 한자리의 일일 때
128 - startDay = int(startTime[9])
129 - else:
130 - startDay = int(startTime[8:10])
131 -
132 -
133 -
134 - endYear = int(endTime[0:4])
135 -
136 - if (int(endTime[5]) == 0): # 한자리의 월일 때
137 - endMonth = int(endTime[6])
138 - else:
139 - endMonth = int(endTime[5:7])
140 -
141 - if (int(endTime[8]) == 0): # 한자리의 일일 때
142 - endDay = int(endTime[9])
143 - else:
144 - endDay = int(endTime[8:10])
145 -
146 - for item in c_List:
147 - itemYear = int(item['time'][0:4])
148 -
149 - if (int(item['time'][5]) == 0): # 한자리의 월일 때
150 - itemMonth = int(item['time'][6])
151 - else:
152 - itemMonth = int(item['time'][5:7])
153 -
154 - if (int(item['time'][8]) == 0): # 한자리의 일일 때
155 - itemDay = int(item['time'][9])
156 - else:
157 - itemDay = int(item['time'][8:10])
158 -
159 - if (itemYear >= startYear and itemYear <= endYear):
160 - if (itemMonth >= startMonth and itemMonth <= endMonth):
161 - if(itemDay >= startDay and itemDay <= endDay):
162 - result_List.append(item)
163 -
164 - return result_List
165 -
166 -def printMostShowed(c_List,limit):
167 - temp = ""
168 - result = ""
169 - for item in c_List:
170 - temp = str(item['comment']) + " "
171 - result = result + temp
172 -
173 - sp = Twitter()
174 -
175 - nouns = sp.nouns(result)
176 -
177 - _cnt = Counter(nouns)
178 -
179 - tempList = []
180 - repCnt = 0
181 -
182 - for i,j in _cnt.most_common(limit):
183 - print(str(repCnt+1)+'. '+str(i)+" : "+str(j))
184 - repCnt += 1
185 -
186 -def printResult(c_List):
187 - for i in range(0,len(c_List)):
188 - print(c_List[i])
189 -
190 -def main ():
191 - ## 시작화면
192 -
193 - _star = '*'
194 - print(_star.center(30,'*'))
195 - print('\n')
196 - headString = '< Naver News Crawling >'
197 - print(headString.center(30,'*'))
198 - print('\n')
199 - print(_star.center(30,'*'))
200 -
201 -
202 - # 검색하고자 하는 url을 입력받는다
203 - _url = input('검색하고자 하는 url을 입력해주세요: ')
204 - print('comment_list를 가져오는 중.....')
205 - cList = getData(_url)
206 - refine_time(cList)
207 - #printMostShowed(cList,10)
208 - print('\n')
209 - print('comment_list를 다 가져왔습니다!')
210 -
211 - while(True):
212 - print('***********************************')
213 - print('1.닉네임 기반 검색')
214 - print('2.키워드 기반 검색')
215 - print('3.작성시간 기반 검색')
216 - print('4.자주 나타난 단어 출력')
217 - menu = input('메뉴를 입력해주세요: ')
218 -
219 - if(menu == str(1)):
220 - print('***********************************')
221 - inputID = input('검색할 닉네임 앞 4자리를 입력해주세요(전 단계로 가시려면 -1을 입력해주세요): ')
222 - if(inputID == str(-1)):
223 - continue
224 - _result = search_by_author(cList,inputID)
225 - printResult(_result)
226 - print(_result)
227 - elif(menu == str(2)):
228 - print('***********************************')
229 - inputKW = input('검색할 키워드를 입력해주세요(전 단계로 가시려면 -1을 입력해주세요): ')
230 - if(inputKW == str(-1)):
231 - continue
232 - _result = search_by_keyword(cList,inputKW)
233 - printResult(_result)
234 - elif(menu == str(3)):
235 - print('***********************************')
236 - print('전 단계로 돌아가시려면 -1을 입력해주세요')
237 - startTime = input('검색할 시간대의 시작일을 입력해주세요(YYYY-MM-DD): ')
238 - endTime = input('검색할 시간대의 마지막 일을 입력해주세요(YYYY-MM-DD): ')
239 -
240 - if(startTime == str(-1) or endTime == str(-1)):
241 - continue
242 -
243 - _result = search_by_time(cList,startTime,endTime)
244 - printResult(_result)
245 - elif(menu == str(4)):
246 - print('***********************************')
247 - inputLimit = input('상위 몇 개 까지 보고 싶은지 입력하세요(1~20): ')
248 - while(True):
249 - if (int(inputLimit) <= 0 or int(inputLimit) > 20):
250 - inputLimit = input('상위 몇 개 까지 보고 싶은지 입력하세요(1~20): ')
251 - else:
252 - break
253 -
254 - printMostShowed(cList,int(inputLimit))
255 - else:
256 - print('잘못된 입력입니다')
257 - continue
258 -
259 -
260 -
261 -main()
1 -현재 검색 기능 구현 완료와 더불어
2 -검색 속도 향상 완료
...\ No newline at end of file ...\ No newline at end of file
1 -적합하지 않은 webtoon 브랜치 삭제
2 -twitter branch 새로 구현
3 -
4 -추가로 twitter에서 댓글 받아오는 것을 아이디, 날짜, 내용, 링크로 구성된
5 -딕셔너리로 만듬
6 -
7 -이를 이용해서 더 구현 예정
...\ No newline at end of file ...\ No newline at end of file
1 -import GetOldTweets3 as got
2 -from bs4 import BeautifulSoup
3 -
4 -import datetime
5 -import time
6 -from random import uniform
7 -from tqdm import tqdm_notebook
8 -
9 -def get_tweets(criteria):
10 - tweet = got.manager.TweetManager.getTweets(criteria)
11 - tweet_list = []
12 -
13 - for index in tqdm_notebook(tweet):
14 -
15 - # 메타데이터 목록
16 - username = index.username
17 - link = index.permalink
18 - content = index.text
19 - tweet_date = index.date.strftime("%Y-%m-%d")
20 - retweets = index.retweets
21 - favorites = index.favorites
22 -
23 - # 결과 합치기
24 - info_list = {'username' : username, 'text': content, 'time': tweet_date, 'link': link}
25 - tweet_list.append(info_list)
26 - # 휴식
27 - time.sleep(uniform(1,2))
28 - print("====================================")
29 - if(len(tweet_list) == 0):
30 - print("조건에 맞는 tweet이 없습니다.")
31 - else:
32 - print(tweet_list)
33 - print("====================================")
34 -days_range = []
35 -
36 -start = datetime.datetime.strptime("2019-11-25", "%Y-%m-%d")
37 -end = datetime.datetime.strptime("2019-11-26", "%Y-%m-%d")
38 -date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
39 -
40 -for date in date_generated:
41 - days_range.append(date.strftime("%Y-%m-%d"))
42 -print("=== 기본으로 설정된 트윗 수집 기간은 {} 에서 {} 까지 입니다 ===".format(days_range[0], days_range[-1]))
43 -print("=== 총 {}일 간의 데이터 수집 ===".format(len(days_range)))
44 -
45 -# 수집 기간 맞추기
46 -start_date = days_range[0]
47 -end_date = (datetime.datetime.strptime(days_range[-1], "%Y-%m-%d")
48 - + datetime.timedelta(days=1)).strftime("%Y-%m-%d") # setUntil이 끝을 포함하지 않으므로, day + 1
49 -
50 -my_key = input("검색할 키워드를 입력해주세요: ")
51 -
52 -while(True):
53 - temp1 = "현재 검색어는 " + my_key + "입니다. "
54 - print(temp1)
55 - print("기간은 기본적으로 최근 1일입니다.")
56 - print("빠른 검색을 지원하기 위해 최대 50건까지만 표시됩니다.")
57 - print("1. 닉네임을 통한 검색")
58 - print("2. 키워드를 통한 검색")
59 - print("3. 시간을 통한 검색")
60 - print("4. 종료")
61 - userNum = int(input("무엇을 하시겠습니까?: "))
62 -
63 - if userNum == 1:
64 - nick = input("검색할 닉네임을 입력해주세요: ")
65 - print("1. 최근 10개만 보기")
66 - print("2. 해당 닉네임의 트윗 50건 보기")
67 - print("3. 현재 검색어를 적용시켜 보기")
68 - tweetNum = int(input("무엇을 하시겠습니까?: "))
69 - if(tweetNum == 1):
70 - tweetCriteria = got.manager.TweetCriteria().setUsername(nick)\
71 - .setSince(start_date)\
72 - .setUntil(end_date)\
73 - .setMaxTweets(10)
74 - get_tweets(tweetCriteria)
75 - elif(tweetNum == 2):
76 - tweetCriteria = got.manager.TweetCriteria().setUsername(nick)\
77 - .setSince(start_date)\
78 - .setUntil(end_date)\
79 - .setMaxTweets(50)
80 - get_tweets(tweetCriteria)
81 - elif(tweetNum == 3):
82 - tweetCriteria = got.manager.TweetCriteria().setUsername(nick)\
83 - .setQuerySearch(my_key)\
84 - .setSince(start_date)\
85 - .setUntil(end_date)\
86 - .setMaxTweets(50)
87 - get_tweets(tweetCriteria)
88 - else:
89 - print("잘못된 보기를 선택하셨습니다.")
90 - elif userNum == 2:
91 - my_key = input("검색할 키워드를 입력해주세요: ")
92 - tweetCriteria = got.manager.TweetCriteria().setQuerySearch(my_key)\
93 - .setSince(start_date)\
94 - .setUntil(end_date)\
95 - .setMaxTweets(50)
96 - get_tweets(tweetCriteria)
97 - elif userNum == 3:
98 - user_start = int(input("시작일을 입력해주세요(yyyymmdd형태): "))
99 - if(user_start < 20170000 or user_start > 20191200):
100 - print("최근 3년 이내만 검색가능합니다.")
101 - continue
102 - user_end = int(input("종료일을 입력해주세요(yyyymmdd형태): "))
103 - if(user_end > 20191200):
104 - print("미래로 갈 수는 없습니다.")
105 - continue
106 - elif(user_end < user_start):
107 - print("시작일보다 작을 수 없습니다.")
108 - continue
109 - if(user_end - 8 > user_start):
110 - print("최대 1주일까지 검색이 가능합니다.")
111 - continue
112 - else:
113 - start_year = user_start // 10000
114 - start_month = user_start // 100 - start_year * 100
115 - start_day = user_start - start_year * 10000 - start_month * 100
116 - end_year = user_end // 10000
117 - end_month = user_end // 100 - end_year * 100
118 - end_day = user_end - end_year * 10000 - end_month * 100
119 - d1 = str(start_year) + "-" + str(start_month) + "-" + str(start_day)
120 - # d2는 보여주기용, d3는 실제 코드에 넣기용(코드에 넣을때는 +1을 해줘야 한다.)
121 - d2 = str(end_year) + "-" + str(end_month) + "-" + str(end_day)
122 - d3 = str(end_year) + "-" + str(end_month) + "-" + str(end_day + 1)
123 - print("1. 현재 검색어를 적용시켜 검색")
124 - print("2. 다른 검색어를 적용시켜 검색")
125 - myNum = int(input("무엇을 선택하시겠습니까?: "))
126 - if(myNum == 1):
127 - print("1. 닉네임을 적용시켜 검색")
128 - print("2. 닉네임 상관없이 전부 검색")
129 - myNum1 = int(input("무엇을 선택하시겠습니까?: "))
130 - if(myNum1 == 1):
131 - nick2 = input("검색할 닉네임을 입력해주세요: ")
132 - tweetCriteria = got.manager.TweetCriteria().setUsername(nick)\
133 - .setQuerySearch(my_key)\
134 - .setSince(d1)\
135 - .setUntil(d3)\
136 - .setMaxTweets(50)
137 - elif(myNum1 == 2):
138 - tweetCriteria = got.manager.TweetCriteria().setQuerySearch(my_key)\
139 - .setSince(d1)\
140 - .setUntil(d3)\
141 - .setMaxTweets(50)
142 - else:
143 - print("잘못된 입력입니다.")
144 - continue
145 - elif(myNum == 2):
146 - my_key = input("검색할 키워드를 입력해주세요: ")
147 - print("1. 닉네임을 적용시켜 검색")
148 - print("2. 닉네임 상관없이 전부 검색")
149 - myNum2 = int(input("무엇을 선택하시겠습니까?: "))
150 - if(myNum2 == 1):
151 - nick2 = input("검색할 닉네임을 입력해주세요: ")
152 - tweetCriteria = got.manager.TweetCriteria().setUsername(nick)\
153 - .setQuerySearch(my_key)\
154 - .setSince(d1)\
155 - .setUntil(d3)\
156 - .setMaxTweets(50)
157 - elif(myNum2 == 2):
158 - tweetCriteria = got.manager.TweetCriteria().setQuerySearch(my_key)\
159 - .setSince(d1)\
160 - .setUntil(d3)\
161 - .setMaxTweets(50)
162 - else:
163 - print("잘못된 입력입니다.")
164 - continue
165 - else:
166 - print("잘못된 입력입니다.")
167 - continue
168 - print("=== 현재 설정된 트윗 수집 기간은 {} 에서 {} 까지 입니다 ===".format(d1, d2))
169 - print("=== 총 {}일 간의 데이터 수집 ===".format(user_end - user_start))
170 - get_tweets(tweetCriteria)
171 - elif userNum == 4:
172 - break
173 - else:
174 - print("잘못된 입력입니다.")
175 - continue
1 -Youtube 3차 수정 사항
2 ------------------------------------------------------
3 -1차에서 추가적으로 구현 할 사항
4 -
5 -1. 명령행 파라미터를 input 으로 넣는 함수
6 -2. csv 파일에서 리스트를 받아오는 함수
7 -3. 받아 온 Data를 가공 처리 하는 함수
8 - * 가장 많이 등장한 키워드 찾는 함수
9 - * 저자를 통해 검색하는 함수
10 - * 내가 쓴 댓글을 확인 하는 함수
11 - * 가장 댓글을 많이 입력한 사람을 찾는 함수
12 ------------------------------------------------------
13 -2차 Update 사항
14 -
15 -1. 명령행 파라미터를 Input으로 변경하여 받도록 수정하였음
16 -2. csv 파일으로 저장 할 것인지 여부를 묻고, 저장 하지 않는 경우 Dictionary 형태로 List에 넣도록 수정하였음
17 -3. Test 형식으로 List에 들어간 값들이 정상적으로 출력되는지 점검하였음
18 ------------------------------------------------------
19 -이후 추가 구현 사항
20 -
21 -1. Module 분리 (List 반환 모듈, Main 부분) -> 굳이 분리하지 않을 경우
22 -추가적으로 함수를 구현해야함
23 -2. 본격적으로 Data Set을 어떤 식으로 분리하여 제공 할지에 대한 추가적인 기능 구현 필요
24 -
25 ------------------------------------------------------
26 -
27 -1. 2차 개발사항에서 오류가 있던 부분을 수정하였음
28 -2. 가져온 Comment를 가공하여 처리할 수 있도록 일부 함수 구현
29 - (1) 키워드를 통해 검색할 수 있도록 함수 구현
30 - (2) 작성자 이름을 통해 검색할 수 있도록 함수 구현
31 -
32 ------------------------------------------------------
33 -추가 구현 사항
34 -
35 -1. konlpy (http://konlpy.org/ko/latest/)를 통하여 명사 추출 후 keyword 분석하기
36 -2. 시간대를 추출하여 시간대 별로 Comment 정리하기
37 ------------------------------------------------------
38 -4차 개발사항
39 -
40 -1. konlpy를 이용하여 keyword 분석 후 가장 많이 등장한 키워드 리스트 출력
41 -2. 1번 기능을 사용하여 wordcloud 구성
42 -3. 시간대를 이용하여 검색할 수 있는 기능 구현
43 -4. 시간대 별로 sort된 리스트를 가질 수 있도록 구현
44 ------------------------------------------------------
45 -추가 구현 사항
46 -
47 -1. 시간대 별로 sort된 리스트를 matplotlib python을 이용하여 차트화 시키기
48 -2. 기능 별로 접근할 수 있도록 정리할 것
49 ------------------------------------------------------
50 -5차 개발사항
51 -
52 -1. 시간대 별로 sort된 리스트를 matplotlib for python을 이용하여 차트화 하였음
...\ No newline at end of file ...\ No newline at end of file