[python-크롤링] 파이썬으로 네이버 뉴스 수집하기 – 기사요약 포함

·

·

,

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

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

아래는 코드 전문입니다.

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

전체코드

# -*- 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)
        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)

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 = f"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:
            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 = f"{now.year}-{now.month}-{now.day} {now.hour}{now.minute}{now.second}초 merging.xlsx"
    df.to_excel(RESULT_PATH + outputFileName, sheet_name='sheet1')

def crawler_csv(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 = f"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:
            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 = f"{now.year}-{now.month}-{now.day} {now.hour}{now.minute}{now.second}초 merging.csv"
    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 = f"20{x:0>2}.01.01"  # 2019.01.01
        e_date = f"20{x:0>2}.12.31"   # 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시간 형태로 나타나는 경우가 존재하며, 이 경우 데이터 오류가 아닌, 수집 시점에서 일주일이 지나지 않을 경우 네이버가 날짜를 표시하지 않아 생기는 문제.

Code language: Python (python)

댓글 남기기