[크롤링]네이버 뉴스 검색 후, 크롤링(제목, 내용요약, 언론사 등)

아마 이 글을 클릭하고 들어온 사람은 파이썬 초보일 것이다.

크롤링을 알기전에 몇가지 알아야 할 부분이 있다.


첫번째, 너무 오래된 블로그의 크롤링 소스는 가져와봤자 무용지물이다.

예를 들어보면 제목대로 네이버 뉴스를 검색 후 크롤링을 하여 가져온다고 치자. 일일히 검색어를 치고, 클릭을 하여  페이지를 넘겨가며 복사 붙여넣기를 하는 수고로움을 하지 않으려고 하는게 크롤링이다. 그러다 보니 클릭을 해서 다음페이지 넘어가는 것을 "프로그램화" 하여 마치 넘어간거 처럼 만들기 위해 소스코드를 짜는 것이다.

이게 네이버 입장에서는 해킹을 하려고 시도하는 것으로 착각을 할 수 있으니, 보안상 혹은 컴퓨터(서버) 부하에 영향을 미치게 되니 이를 막기위해서 HTLML 소스의 방식을 어느 일정 기간마다 변경을 하고 있다.

따라서 몇년전에 잘 돌아가던 크롤링 소스가 이제는 무용지물인 경험을 할 수 있을 것이다.


두번째, 네이버에서 돌아간다고 다음에서도 돌아가지 않을 수도...

완벽한 소스는 없다. 모든 포털 사이트의 뉴스기사가 동일한 형태의 소스로 짜여져 있다면 좋겠지만, 그렇지는 않다. 네이버 뉴스를 위해 짠 소스는 어쩌면 네이버 뉴스에서만 돌아갈 가능성이 높다.(쓰니도 해보지는 않음)
단, 크롤링 구조를 완벽히 이해를 한다면 응용이 가능 하겠지...




여튼, 각설하고 소스 코드를 공개한다. (이 글은 2021년 1월 3일에 쓴 글로, 해당 시점에 크롤링 정상으로 되는 것 확인)


 # -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from datetime import datetime
import requests
import pandas as pd
import re

#한글깨짐 방지
import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding = 'utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding = 'utf-8')

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
< naver 뉴스 검색시 리스트 크롤링하는 프로그램 > _select사용
- 크롤링 해오는 것 : 링크,제목,신문사,내용요약본
- 내용요약본  -> 정제 작업 필요
- 리스트 -> 딕셔너리 -> df -> 엑셀로 저장
'''''''''''''''''''''

#각 크롤링 결과 저장하기 위한 리스트 선언
title_text=[]
link_text=[]
source_text=[]
contents_text=[]
result={}

#엑셀로 저장하기 위한 변수
RESULT_PATH ='C:/'  #결과 저장할 경로
now = datetime.now() #파일이름 현 시간으로 저장하기

#내용 정제화 함수
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>태그에서 제목과 링크주소 (a 태그 중 class 명이 news_tit인 것)
        atags = soup.find_all('a', 'news_tit')
        for atag in atags:
            title = atag.get('title')
            title_text.append(title)     #제목
            link_text.append(atag['href'])   #링크주소

        #신문사 추출 (a 태그 중 class 명이 info press인 것)
        source_lists = soup.find_all('a', 'info press')
        for source_list in source_lists:
            source_text.append(source_list.text)    #신문사

        #본문요약본 (a 태그 중 class 명이 api_txt_lines dsc_txt_wrap인 것)
        contents_lists = soup.find_all('a','api_txt_lines dsc_txt_wrap')
        for contents_list in contents_lists:
            contents_cleansing(contents_list) #본문요약 정제화

        #모든 리스트 딕셔너리형태로 저장
        result= {"title":title_text ,  "source" : source_text ,"contents": contents_text ,"link":link_text }
        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 main():
    info_main = input("="*50+"\n"+"입력 형식에 맞게 입력해주세요."+"\n"+" 시작하시려면 Enter를 눌러주세요."+"\n"+"="*50)
    maxpage = input("최대 크롤링할 페이지 수 입력하시오: ") #10,20...
    query = input("검색어 입력: ") #네이버, 부동산...
    sort = input("뉴스 검색 방식 입력(관련도순=0  최신순=1  오래된순=2): ")    #관련도순=0  최신순=1  오래된순=2
    s_date = input("시작날짜 입력(2019.01.04):")  #2019.01.04
    e_date = input("끝날짜 입력(2019.01.05):")   #2019.01.05
    crawler(maxpage,query,sort,s_date,e_date)

#메인함수 수행
main()




소스의 구조는 어렵지 않다.


1. main 함수 수행

2. main()함수 호출

3. input값 설정

4. main() 함수 내 crawler() 함수 수행


크게는 위의 네가지 프로세스를 수행한다


위의 소스에서 특이사항이 있는 부분은 아래서 설명한다.



input: 네이버에서 검색하고자 하는 검색어, 검색기간, 뉴스 검색 방식, 최대 페이지수 등을 설정하는 부분으로 사용자 임으로 변경 가능


url  : 네이버 뉴스에서 "네이버" 검색 했을 때 나오는 URL을 기반으로 한다.


크롤링하는 값: 맨 위에 주의해야할 점 첫번째에 해당하는 내용이다. 위 소스를 짜기 위해 여러 소스를 참조했는데, 실제로는 수행이 안되어 찾아보니 해당 부분이 잘 못 되어 있는 것을 확인했다. 현재 네이버 뉴스의 제목은 a태그 중에 class 명이 nesw_tit인 값을 가지고 오고 있는 것을 확인하고 저 부분을 수정하니 정상적으로 나오게 되었다.



자바와 다르게 파이썬은 너무 민감한 프로그램인 것 같다. 띄어쓰기나 줄간격 등에 예민해서 웹 상의 소스를 복붙하면 정상적인 코드라도 복사 붙여넣기 과정에서 줄바꿈이 들어가 안돌아가는 경우도 태반이다.

가장 좋은 방법은 메모장에 붙여 넣고 그다음에 정제한 후, 붙여넣으면 어느정도 오류를 줄일 수 있다.



Designed by JB FACTORY