네이버에서 검색한 뉴스를 긁어오는 코드입니다. 각 홈페이지로 리다이렉트 되는 기사의 경우 주소의 일관성이 없어서 기사 내용은 불러오지 못 합니다. 앞의 “기사내용 포함하여 네이버 뉴스 수집하기”와 다른 점은 기사 내용은 긁어오지 못 하지만, 네이버 뉴스에서 검색해서 나타나는 모든 기사를 각 기사의 요약과 함께 수집합니다.

자세한 설명은 추후 시간이 날 때 하도록 하겠습니다.

아래는 코드 전문입니다.

불필요한 코드들이 중간에 섞여 있습니다.

전체코드

# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from datetime import datetime
import requests
import pandas as pd
import re
 
# 각 크롤링 결과 저장하기 위한 리스트 선언
title_text = []
link_text = []
source_text = []
date_text = []
contents_text = []
result = {}
 
# 엑셀로 저장하기 위한 변수
RESULT_PATH = 'D:/키워드 분석/네이버뉴스(01)/'  # 결과 저장할 경로
now = datetime.now()  # 파일이름 현 시간으로 저장하기
 
# %%
# 뉴스 수집을 위한 def입니다.
# 날짜 정제화 함수
 
def date_cleansing(test):
    try:
        # 지난 뉴스
        # 머니투데이  10면1단  2018.11.05. 네이버뉴스   보내기
        pattern = '\\\\d+.(\\\\d+).(\\\\d+).'  # 정규표현식
 
        r = re.compile(pattern)
        match = r.search(test).group(0)  # 2018.11.05.
        date_text.append(match)
 
    except AttributeError:
        # 최근 뉴스
        # 이데일리 1시간 전 네이버뉴스 보내기
        pattern = '\\\\w* (\\\\d\\\\w*)'  # 정규표현식
 
        r = re.compile(pattern)
        match = r.search(test).group(1)
        # print(match)
        date_text.append(match)
 
# 내용 정제화 함수
 
def contents_cleansing(contents):
    first_cleansing_contents = re.sub('<dl>.*?</a> </div> </dd> <dd>', '',
                                      str(contents)).strip()  # 앞에 필요없는 부분 제거
    second_cleansing_contents = re.sub('<ul class="relation_lst">.*?</dd>', '',
                                       first_cleansing_contents).strip()  # 뒤에 필요없는 부분 제거 (새끼 기사)
    third_cleansing_contents = re.sub('<.+?>', '', second_cleansing_contents).strip()
    contents_text.append(third_cleansing_contents)
    # print(contents_text)
 
def crawler(maxpage, query, sort, s_date, e_date):
 
    s_from = s_date.replace(".","")
    e_to = e_date.replace(".","")
    page = 1
    maxpage_t = (int(maxpage) - 1) * 10 + 1  # 11= 2페이지 21=3페이지 31=4페이지  ...81=9페이지 , 91=10페이지, 101=11페이지
 
    while page <= maxpage_t:
        url = "<https://search.naver.com/search.naver?where=news&query=>" + query + "&sort=" + sort + "&ds=" + s_date + "&de=" + e_date + "&nso=so%3Ar%2Cp%3Afrom" + s_from + "to" + e_to + "%2Ca%3A&start=" + str(page)
 
        response = requests.get(url)
        html = response.text
 
        # 뷰티풀소프의 인자값 지정
        soup = BeautifulSoup(html, 'html.parser')
 
        # <a>태그에서 제목과 링크주소 추출
        atags = soup.select('._sp_each_title')
        for atag in atags:
            title_text.append(atag.text)     # 제목
            link_text.append(atag['href'])   # 링크주소
 
        # 신문사 추출
        source_lists = soup.select('._sp_each_source')
        for source_list in source_lists:
            source_text.append(source_list.text)  # 신문사
 
        # 날짜 추출
        date_lists = soup.select('.txt_inline')
        for date_list in date_lists:
            test = date_list.text
            date_cleansing(test)  # 날짜 정제 함수사용
 
        # 본문요약본
        contents_lists = soup.select('ul.type01 dl')
        for contents_list in contents_lists:
            # print('==='*40)
            # print(contents_list)
            contents_cleansing(contents_list)  # 본문요약 정제화
 
        # 모든 리스트 딕셔너리형태로 저장
        result ="date": date_text, "title": title_text, "source": source_text, "contents": contents_text, "link": link_text}
        print(page)
 
        df = pd.DataFrame(result)  # df로 변환
        page += 10
 
    # 새로 만들 파일이름 지정
    outputFileName = '%s-%s-%s  %s시 %s분 %s초 merging.xlsx' % (now.year, now.month, now.day, now.hour, now.minute, now.second)
    df.to_excel(RESULT_PATH + outputFileName, sheet_name='sheet1')
 
def crawler_csv(maxpage, query, sort, s_date, e_date):  # 엑셀이 아닌 csv로 작성하기
 
    s_from = s_date.replace(".", "")
    e_to = e_date.replace(".", "")
    page = 1
    maxpage_t = (int(maxpage) - 1) * 10 + 1  # 11 = 2페이지 21 = 3페이지 31 = 4페이지...81 = 9페이지, 91 = 10페이지, 101 = 11페이지
 
    while page <= maxpage_t:
        url = "<https://search.naver.com/search.naver?where=news&query=>" + query + "&sort="+sort+"&ds=" + s_date + "&de=" + e_date + "&nso=so%3Ar%2Cp%3Afrom" + s_from + "to" + e_to + "%2Ca%3A&start=" + str(page)
 
        response = requests.get(url)
        html = response.text
 
        # 뷰티풀소프의 인자값 지정
        soup = BeautifulSoup(html, 'html.parser')
 
        # <a>태그에서 제목과 링크주소 추출
        atags = soup.select('._sp_each_title')
        for atag in atags:
            title_text.append(atag.text)     # 제목
            link_text.append(atag['href'])   # 링크주소
 
        # 신문사 추출
        source_lists = soup.select('._sp_each_source')
        for source_list in source_lists:
            source_text.append(source_list.text)    # 신문사
 
        # 날짜 추출
        date_lists = soup.select('.txt_inline')
        for date_list in date_lists:
            test = date_list.text
            date_cleansing(test)  # 날짜 정제 함수사용
 
        # 본문요약본
        contents_lists = soup.select('ul.type01 dl')
        for contents_list in contents_lists:
            # print('==='*40)
            # print(contents_list)
            contents_cleansing(contents_list)  # 본문요약 정제화
 
        # 모든 리스트 딕셔너리형태로 저장
        result ="date": date_text, "title": title_text, "source": source_text, "contents": contents_text, "link": link_text}
        print(page)
 
        df = pd.DataFrame(result)  # df로 변환
        page += 10
 
    # 새로 만들 파일이름 지정
    outputFileName = '%s-%s-%s  %s시 %s분 %s초 merging.csv' % (now.year, now.month, now.day, now.hour, now.minute, now.second)
    df.to_csv(RESULT_PATH + outputFileName, mode='a', sep="")
 
def main_mod():
    x = 0  # 연도별로 반복시키기 위해서(400줄 이상 네이버가 검색 결과를 제공하지 않기 때문에, 400줄 단위로 작업해야 하며, 연도를 나눠야 한다.)
    while x < 20:
        maxpage = 400
        query = '"문화영향평가"'
        sort = "0"
        s_date = "20{0:0>2}.01.01".format(x)  # 2019.01.01
        e_date = "20{0:0>2}.12.31".format(x)   # 2019.04.28
 
        crawler_csv(maxpage, query, sort, s_date, e_date)
 
        x += 1
 
# %%
main_mod()
 
# %%
# 경우에 따라 마지막 뉴스가 수백번 중복되는 경우가 발생하여 중복 제거가 필요
import csv
 
my_columns = [1, 2, 3, 4, 5]
 
with open('D:/키워드 분석/네이버뉴스(01)/contents.csv', 'r', encoding='utf-8') as f:
    with open('D:/키워드 분석/네이버뉴스(01)/contents_mod.txt', 'w', encoding='utf-8') as nf:
        filereader = csv.reader(f)
        filewriter = csv.writer(nf)  # 헤더를 안 지우는 이유는 이미 여러번 들어가 있다.
        for row_list in filereader:
            row_list_output = []
            for index_value in my_columns:
                row_list_output.append(row_list[index_value])
            filewriter.writerow(row_list_output)
 
with open('D:/키워드 분석/네이버뉴스(01)/contents_mod.txt', 'r', encoding='utf-8') as f:
    list_file = f.readlines()
list_file = [line.rstrip('\\\\n') for line in list_file]
 
new_list = list(set(list_file))  # 중복 뉴스기사 제거하기
 
with open('D:/키워드 분석/네이버뉴스(01)/contents_mod.txt', 'w', encoding='utf-8') as nf:
    for line in new_list:
        nf.write(line + '\\\\n')
 
# 헤더(date,title,source,contents,link)가 여러번 들어가 있으나, 중복 제거에서 한 번만 남는다. 위치는 어디인지 알 수 없다.
 
# 날짜가 아닌, 1일 7일 5시간 형태로 나타나는 경우가 존재하며, 이 경우 데이터 오류가 아닌, 수집 시점에서 일주일이 지나지 않을 경우 네이버가 날짜를 표시하지 않아 생기는 문제.