def crawling(self, category_name): # Multi Process PID print(category_name + " PID: " + str(os.getpid())) writer = Writer(category='Article', article_category=category_name, date=self.date) # 기사 url 형식 url_format = f'http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1={self.categories.get(category_name)}&date=' # start_year년 start_month월 ~ end_year의 end_month 날짜까지 기사를 수집합니다. target_urls = self.make_news_page_url(url_format, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print(category_name + " Urls are generated") print("The crawler starts") for url in target_urls: request = self.get_url_data(url) document = BeautifulSoup(request.content, 'html.parser') # html - newsflash_body - type06_headline, type06 # 각 페이지에 있는 기사들 가져오기 temp_post = document.select('.newsflash_body .type06_headline li dl') temp_post.extend(document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post_urls = [] for line in temp_post: # 해당되는 page에서 모든 기사들의 URL을 post_urls 리스트에 넣음 post_urls.append(line.a.get('href')) del temp_post for content_url in post_urls: # 기사 url # 크롤링 대기 시간 sleep(0.01) # 기사 HTML 가져옴 request_content = self.get_url_data(content_url) try: document_content = BeautifulSoup(request_content.content, 'html.parser') except: continue try: # 기사 제목 가져옴 tag_headline = document_content.find_all('h3', {'id': 'articleTitle'}, {'class': 'tts_head'}) # 뉴스 기사 제목 초기화 text_headline = '' text_headline = text_headline + ArticleParser.clear_headline(str(tag_headline[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_headline: continue # 기사 본문 가져옴 tag_content = document_content.find_all('div', {'id': 'articleBodyContents'}) # 뉴스 기사 본문 초기화 text_sentence = '' text_sentence = text_sentence + ArticleParser.clear_content(str(tag_content[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_sentence: continue # 기사 언론사 가져옴 tag_company = document_content.find_all('meta', {'property': 'me2:category1'}) # 언론사 초기화 text_company = '' text_company = text_company + str(tag_company[0].get('content')) # 공백일 경우 기사 제외 처리 if not text_company: continue # 기사 시간대 가져옴 time = re.findall('<span class="t11">(.*)</span>',request_content.text)[0] # CSV 작성 writer.write_row([time, category_name, text_company, text_headline, text_sentence, content_url]) del time del text_company, text_sentence, text_headline del tag_company del tag_content, tag_headline del request_content, document_content # UnicodeEncodeError except Exception as ex: del request_content, document_content pass writer.close()
def crawling(self, category_name): # Multi Process PID print(category_name + " PID: " + str(os.getpid())) writer = Writer(category_name=category_name, date=self.date) # 기사 URL 형식 url = "http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1=" + str( self.categories.get(category_name)) + "&date=" # start_year년 start_month월 ~ end_year의 end_month 날짜까지 기사를 수집합니다. day_urls = self.make_news_page_url(url, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print(category_name + " Urls are generated") print("The crawler starts") for URL in day_urls: regex = re.compile("date=(\d+)") news_date = regex.findall(URL)[0] request = self.get_url_data(URL) document = BeautifulSoup(request.content, 'html.parser') # html - newsflash_body - type06_headline, type06 # 각 페이지에 있는 기사들 가져오기 post_temp = document.select( '.newsflash_body .type06_headline li dl') post_temp.extend(document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post = [] for line in post_temp: post.append(line.a.get( 'href')) # 해당되는 page에서 모든 기사들의 URL을 post 리스트에 넣음 del post_temp for content_url in post: # 기사 URL # 크롤링 대기 시간 sleep(0.01) # 기사 HTML 가져옴 request_content = self.get_url_data(content_url) try: document_content = BeautifulSoup(request_content.content, 'html.parser') except: continue try: # 기사 제목 가져옴 tag_headline = document_content.find_all( 'h3', {'id': 'articleTitle'}, {'class': 'tts_head'}) text_headline = '' # 뉴스 기사 제목 초기화 text_headline = text_headline + ArticleParser.clear_headline( str(tag_headline[0].find_all(text=True))) if not text_headline: # 공백일 경우 기사 제외 처리 continue # 기사 본문 가져옴 tag_content = document_content.find_all( 'div', {'id': 'articleBodyContents'}) text_sentence = '' # 뉴스 기사 본문 초기화 text_sentence = text_sentence + ArticleParser.clear_content( str(tag_content[0].find_all(text=True))) if not text_sentence: # 공백일 경우 기사 제외 처리 continue # 기사 언론사 가져옴 #tag_company = document_content.find_all('meta', {'property': 'me2:category1'}) #text_company = '' # 언론사 초기화 #text_company = text_company + str(tag_company[0].get('content')) #if not text_company: # 공백일 경우 기사 제외 처리 # continue # CSV 작성 wcsv = writer.get_writer_csv() wcsv.writerow([text_headline, text_sentence]) del text_company, text_sentence, text_headline del tag_company del tag_content, tag_headline del request_content, document_content except Exception as ex: # UnicodeEncodeError .. # wcsv.writerow([ex, content_url]) del request_content, document_content pass writer.close()
def crawling(self, category_name): # Multi Process PID print(category_name + " PID: " + str(os.getpid())) writer = Writer(category='Article', article_category=category_name, date=self.date) # 기사 url 형식 url_format = f'http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1={self.categories.get(category_name)}&date=' # start_year년 start_month월 ~ end_year의 end_month 날짜까지 기사를 수집합니다. target_urls = self.make_news_page_url(url_format, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print(category_name + " Urls are generated") print("The crawler starts") for index, url in enumerate(target_urls): if index % 100 == 0: print(index, ' : ', url, round(index / len(target_urls) * 100, 2), '%') request = self.get_url_data(url) document = BeautifulSoup(request.content, 'html.parser') # html - newsflash_body - type06_headline, type06 # 각 페이지에 있는 기사들 가져오기 temp_post = document.select( '.newsflash_body .type06_headline li dl') temp_post.extend(document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post_urls = [] for line in temp_post: # 해당되는 page에서 모든 기사들의 URL을 post_urls 리스트에 넣음 post_urls.append(line.a.get('href')) del temp_post for content_url in post_urls: # 기사 url # 크롤링 대기 시간 sleep(0.01) # 기사 HTML 가져옴 request_content = self.get_url_data(content_url) try: document_content = BeautifulSoup(request_content.content, 'html.parser') except: continue try: # 기사 제목 가져옴 tag_headline = document_content.find_all( 'h3', {'id': 'articleTitle'}, {'class': 'tts_head'}) # 뉴스 기사 제목 초기화 text_headline = '' text_headline = text_headline + ArticleParser.clear_headline( str(tag_headline[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_headline: continue # 기사 본문 가져옴 tag_content = document_content.find_all( 'div', {'id': 'articleBodyContents'}) # 뉴스 기사 본문 초기화 text_sentence = '' text_sentence = text_sentence + ArticleParser.clear_content( str(tag_content[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_sentence: continue # 기사 언론사 가져옴 tag_company = document_content.find_all( 'meta', {'property': 'me2:category1'}) # 언론사 초기화 text_company = '' text_company = text_company + str( tag_company[0].get('content')) # 공백일 경우 기사 제외 처리 if not text_company: continue # 기사 시간대 가져옴 time_list = re.findall('<span class="t11">(.*)</span>', request_content.text) time = time_list[0] #기사 작성 시간 if len(time_list) >= 2: modify_time = time_list[1] #기사 수정 시간 else: modify_time = '' #2020123추가 #Reaction추가 oid = re.findall('oid=(.*)&', content_url)[0] aid = re.findall('aid=(.*)', content_url)[0] reaction_url = 'https://news.like.naver.com/v1/search/contents?q=NEWS[ne_{}_{}]'.format( oid, aid) #웹에서 동적으로 받아와짐 => 기사의 oid, aid 활용하여 동적접근 reaction_req = requests.get(reaction_url) reaction_html = reaction_req.text reaction_json = json.loads( reaction_html)['contents'][0]['reactions'] reactionCountList = [0, 0, 0, 0, 0] reactList = np.array( ['like', 'warm', 'sad', 'angry', 'want']) for countIndex, reaction in enumerate(reactList): if reaction not in [ i['reactionType'] for i in reaction_json ]: # 값이 없는 리액션은 넘어감 continue reaction_index = [ i['reactionType'] for i in reaction_json ].index(reaction) reactionCountList[countIndex] = reaction_json[ reaction_index]['count'] timestamp = int( str(json.loads(reaction_html)['timestamp'])[:10]) # CSV 작성 writer.write_row([ time, category_name, text_company, text_headline, text_sentence, content_url, modify_time, reactionCountList, timestamp ]) del time, modify_time del text_company, text_sentence, text_headline del tag_company del tag_content, tag_headline del request_content, document_content # UnicodeEncodeError except Exception as ex: del request_content, document_content pass writer.close()
def crawling(self, category_name: str = '경제'): """크롤링 시작.""" pid = str(os.getpid()) if self.logger is not None: self.logger.info(f"카테고리:{category_name} | PID: {pid}") writer = Writer(category='Article', article_category=category_name, date=self.date, root=self.write_root) url_format = \ f"http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&" + \ f"sid1={self.categories.get(category_name)}&date=" target_urls = self.make_news_page_url( category_url=url_format, start_year=self.date['start_year'], end_year=self.date['end_year'], start_month=self.date['start_month'], end_month=self.date['end_month']) if self.logger is not None: self.logger.info(f"URLs generated for {category_name}. Start!") # Write headers for csv file writer.write_row(['일시', '카테고리', '언론사', '제목', '본문', 'url']) #for url in tqdm.tqdm(target_urls, desc=category_name, position=0, leave=True): _process = mp.current_process() total = len(target_urls) position = self.selected_categories.index(category_name) with tqdm.tqdm(desc=f"Keyword: {category_name}", total=total, position=position) as pg: for url in target_urls: request = self.get_url_data(url) if request is None: continue document = BeautifulSoup(request.content, 'html.parser') # html - newsflash_body - type06_headline, type06 # 각 페이지에 있는 기사들 가져오기 temp_post = document.select( '.newsflash_body .type06_headline li dl') temp_post.extend( document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post_urls = [] for line in temp_post: # 해당되는 page에서 모든 기사들의 URL을 post_urls 리스트에 넣음 post_urls.append(line.a.get('href')) del temp_post # 기사 url for content_url in post_urls: # 크롤링 대기 시간 sleep(0.01) # 기사 HTML 가져옴 request_content = self.get_url_data(content_url) if request_content is None: continue try: document_content = BeautifulSoup( request_content.content, 'html.parser') except: continue try: # 기사 제목 가져옴 tag_headline = document_content.find_all( 'h3', {'id': 'articleTitle'}, {'class': 'tts_head'}) # 뉴스 기사 제목 초기화 text_headline = '' text_headline = text_headline + ArticleParser.clear_headline( str(tag_headline[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_headline: continue # 기사 본문 가져옴 tag_content = document_content.find_all( 'div', {'id': 'articleBodyContents'}) # 뉴스 기사 본문 초기화 text_sentence = '' text_sentence = text_sentence + ArticleParser.clear_content( str(tag_content[0].find_all(text=True))) # 공백일 경우 기사 제외 처리 if not text_sentence: continue # 기사 언론사 가져옴 tag_company = document_content.find_all( 'meta', {'property': 'me2:category1'}) # 언론사 초기화 text_company = '' text_company = text_company + str( tag_company[0].get('content')) # 공백일 경우 기사 제외 처리 if not text_company: continue # 기사 시간대 가져옴 time = re.findall('<span class="t11">(.*)</span>', request_content.text)[0] # CSV 작성 writer.write_row([ time, category_name, text_company, text_headline, text_sentence, content_url ]) del time del text_company, text_sentence, text_headline del tag_company del tag_content, tag_headline del request_content, document_content # UnicodeEncodeError except Exception as ex: del request_content, document_content pass pg.update(1) writer.close()
def crawling(self, category_name): writer = Writer(category='Sport', article_category=category_name, date=self.date) url_category = [self.category[category_name]] category = [category_name] title_script = [] office_name_script = [] time_script = [] matched_content = [] # URL 카테고리. Multiprocessing시 어차피 1번 도는거라 refactoring할 필요 있어보임 for url_label in url_category: # URL 인덱스와 category 인덱스가 일치할 경우 그 값도 일치 category = category[url_category.index(url_label)] url = f'https://sports.news.naver.com/{url_label}/news/list.nhn?isphoto=N&view=photo&date=' final_url_day = self.make_sport_page_url(url, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print("succeed making url") if len(str(self.date['start_month'])) == 2: start_month = str(self.date['start_month']) else: start_month = '0' + str(self.date['start_month']) if len(str(self.date['end_month'])) == 2: end_month = str(self.date['end_month']) else: end_month = '0' + str(self.date['end_month']) # 이는 크롤링이 아닌 csv에 사용 hefscript2 = [] # category Year Month Data Page 처리 된 URL for list_page in final_url_day: # 제목 / URL request_content = requests.get( list_page, headers={'User-Agent': 'Mozilla/5.0'}) content_dict = json.loads(request_content.text) # 이는 크롤링에 사용 hefscript = [] for contents in content_dict["list"]: oid = contents['oid'] aid = contents['aid'] title_script.append(contents['title']) time_script.append(contents['datetime']) hefscript.append( "https://sports.news.naver.com/news.nhn?oid=" + oid + "&aid=" + aid) hefscript2.append( "https://sports.news.naver.com/news.nhn?oid=" + oid + "&aid=" + aid) office_name_script.append(contents['officeName']) # 본문 # content page 기반하여 본문을 하면 된다. text_sentence에 본문을 넣고 Clearcontent진행 후 completed_conten_match에 append해주면 된다. # 추가적으로 pass_match에 언론사를 집어넣으면 된다. for content_page in hefscript: sleep(0.01) content_request_content = requests.get( content_page, headers={'User-Agent': 'Mozilla/5.0'}) content_document_content = BeautifulSoup( content_request_content.content, 'html.parser') content_tag_content = content_document_content.find_all( 'div', {'class': 'news_end'}, {'id': 'newsEndContents'}) # 뉴스 기사 본문 내용 초기화 text_sentence = '' try: text_sentence = text_sentence + str( content_tag_content[0].find_all(text=True)) matched_content.append( self.clear_content(text_sentence)) except: pass # Csv 작성 for csv_timeline, csv_headline, csv_content, csv_press, csv_url in zip( time_script, title_script, matched_content, office_name_script, hefscript2): try: if not csv_timeline: continue if not csv_headline: continue if not csv_content: continue if not csv_press: continue if not csv_url: continue writer.write_row([ csv_timeline, self.clear_headline(csv_headline), csv_content, csv_press, category, csv_url ]) except: pass writer.close()
def crawling(self, category_name): # Multi Process PID print(category_name + " PID: " + str(os.getpid())) writer = Writer(category_name=category_name, date=self.date) # 기사 URL 형식 url = "http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1=" + str( self.categories.get(category_name)) + "&date=" # 설정 기간 동안 crawling day_urls = self.make_news_page_url(url, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month'], self.date['start_date'], self.date['end_date']) print(category_name + " Urls are generated") print("The crawler starts") for URL in day_urls: regex = re.compile("date=(\d+)") news_date = regex.findall(URL)[0] request = self.get_url_data(URL) document = BeautifulSoup(request.content, 'html.parser') # 각 페이지에 있는 기사들 가져오기 post_temp = document.select( '.newsflash_body .type06_headline li dl') post_temp.extend(document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post = [] for line in post_temp: post.append(line.a.get( 'href')) # 해당되는 page에서 모든 기사들의 URL을 post 리스트에 넣음 del post_temp for content_url in post: # 기사 URL # 크롤링 대기 시간 sleep(0.01) # 기사 HTML 가져옴 request_content = self.get_url_data(content_url) try: document_content = BeautifulSoup(request_content.content, 'html.parser') except: continue try: # 기사 제목 가져옴 tag_headline = document_content.find_all( 'h3', {'id': 'articleTitle'}, {'class': 'tts_head'}) text_headline = '' # 뉴스 기사 제목 초기화 text_headline = text_headline + ArticleParser.clear_headline( str(tag_headline[0].find_all(text=True))) #keyword 검사 if not self.keyword in text_headline: continue if not text_headline: # 공백일 경우 기사 제외 처리 continue # 기사 본문 가져옴 tag_content = document_content.find_all( 'div', {'id': 'articleBodyContents'}) text_sentence = '' # 뉴스 기사 본문 초기화 text_sentence = text_sentence + ArticleParser.clear_content( str(tag_content[0].find_all(text=True))) #keyword 검사 if not self.keyword in text_sentence: continue if not text_sentence: # 공백일 경우 기사 제외 처리 continue # 기사 언론사 가져옴 tag_company = document_content.find_all( 'meta', {'property': 'me2:category1'}) text_company = '' # 언론사 초기화 text_company = text_company + str( tag_company[0].get('content')) if not text_company: # 공백일 경우 기사 제외 처리 continue #사진 저장 if (self.captureFlag): browser = webdriver.Chrome( ChromeDriverManager().install()) browser.get(content_url) #element not found error 처리 try: element = browser.find_element_by_class_name( 'end_photo_org') location = element.location y = location.get('y') #사진 padding 처리 (y-60) browser.execute_script("window.scrollTo(%d,%d);" % (0, y - 60)) size = element.size title = text_headline + '.png' #기사 제목으로 사진제목 설정 element.screenshot(title) except Exception as ex: print('Not find element') browser.quit() # CSV 작성 wcsv = writer.get_writer_csv() wcsv.writerow([ news_date, category_name, text_company, text_headline, text_sentence, content_url ]) print('작성완료') del text_company, text_sentence, text_headline del tag_company del tag_content, tag_headline del request_content, document_content except Exception as ex: del request_content, document_content pass writer.close()
def crawling(self, category_name): writer = Writer(category='Sport', article_category=category_name, date=self.date) url_category = [self.category[category_name]] category = [category_name] # URL 카테고리. Multiprocessing시 어차피 1번 도는거라 refactoring할 필요 있어보임 for url_label in url_category: # URL 인덱스와 category 인덱스가 일치할 경우 그 값도 일치 category = category[url_category.index(url_label)] url = f'https://sports.news.naver.com/{url_label}/news/list.nhn?isphoto=N&view=photo&date=' final_url_day = self.make_sport_page_url(url, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print("succeed making url") print("crawler starts") if len(str(self.date['start_month'])) == 2: start_month = str(self.date['start_month']) else: start_month = '0' + str(self.date['start_month']) if len(str(self.date['end_month'])) == 2: end_month = str(self.date['end_month']) else: end_month = '0' + str(self.date['end_month']) # category Year Month Data Page 처리 된 URL for list_page in final_url_day: title_script = '' office_name_script = '' time_script = '' matched_content = '' # 제목 / URL request_content = requests.get( list_page, headers={'User-Agent': 'Mozilla/5.0'}) content_dict = json.loads(request_content.text) # 이는 크롤링에 사용 hef_script = '' for contents in content_dict["list"]: oid = contents['oid'] aid = contents['aid'] title_script = contents['title'] time_script = contents['datetime'] hef_script = "https://sports.news.naver.com/news.nhn?oid=" + oid + "&aid=" + aid office_name_script = contents['officeName'] sleep(0.01) content_request_content = requests.get( hef_script, headers={'User-Agent': 'Mozilla/5.0'}) content_document_content = BeautifulSoup( content_request_content.content, 'html.parser') content_tag_content = content_document_content.find_all( 'div', {'class': 'news_end'}, {'id': 'newsEndContents'}) # 뉴스 기사 본문 내용 초기화 text_sentence = '' try: text_sentence = text_sentence + str( content_tag_content[0].find_all(text=True)) matched_content = self.clear_content(text_sentence) writer.write_row([ time_script, category, office_name_script, self.clear_headline(title_script), matched_content, hef_script ]) except: pass writer.close()
def crawling(self, category_name): # Multi Process PID print(category_name + " PID: " + str(os.getpid())) writer = Writer(category_name=category_name, date=self.date) # 기사 URL 형식 if (category_name == "연합뉴스속보"): url = "http://news.naver.com/main/list.nhn?mode=LPOD&mid=sec&sid1=001&sid2=140&oid=001&isYeonhapFlash=Y" \ + "&date=" else: url = "http://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1=" + str( self.categories.get(category_name)) + "&date=" # start_year년 start_month월 ~ end_year의 end_month 날짜까지 기사를 수집합니다. day_urls = self.make_news_page_url(url, self.date['start_year'], self.date['end_year'], self.date['start_month'], self.date['end_month']) print(category_name + " Urls are generated") print("The crawler starts") for URL in day_urls: print(URL) regex = re.compile("date=(\d+)") news_date = regex.findall(URL)[0] request = self.get_url_data(URL) document = BeautifulSoup(request.content, 'html.parser') # html - newsflash_body - type06_headline, type06 # 각 페이지에 있는 기사들 가져오기 if (category_name == "연합뉴스속보"): post_temp = document.select('.newsflash_body .type02 li ') else: post_temp = document.select('.newsflash_body .type06_headline li dl') post_temp.extend(document.select('.newsflash_body .type06 li dl')) # 각 페이지에 있는 기사들의 url 저장 post = [] headlines = [] companys = [] for line in post_temp: post.append(line.a.get('href')) # 해당되는 page에서 모든 기사들의 URL을 post 리스트에 넣음 try: companys.append(line.find('span', class_="writing").text) except: companys.append("err") try: h = line.find_all('a') if len(h) > 1: headlines.append(h[1].text) elif len(h) == 1: headlines.append(h[0].text) else: headlines.append("err") except: headlines.append("err") del post_temp print(len(post)) for i in range(len(post)): # 기사 URL # 크롤링 대기 시간 print(i) sleep(0.01) content_url = post[i] # 기사 HTML 가져옴 try: article = Article(content_url, language='ko') article.download() article.parse() text_sentence = article.text.strip() text_company = companys[i] text_headline = headlines[i].strip() ###################################################################### if self.keyword == 'initvalue': wcsv = writer.get_writer_csv() wcsv.writerow([news_date, category_name, text_company, text_headline, text_sentence, content_url]) else: headline_to_words = text_headline.split() if headline_to_words.index(self.keyword) >= 0: wcsv = writer.get_writer_csv() wcsv.writerow([news_date, category_name, text_company, text_headline, text_sentence, content_url]) ###################################################################### except Exception as err: print(err) writer.close() return