TIL No.13: Python - 네이버 뉴스에서 헤드라인 뉴스 목록 크롤링해서 저장하기

BLAKE KIM·2020년 7월 1일
0

import urllib.request, urllib.parse, urllib.error
from bs4 import BeautifulSoup
from datetime import datetime
import pandas

urllib.request는 URL(Uniform Resource Locator)을 가져오기 위한 파이썬 모듈입니다. urlopen 함수의 형태로, 매우 간단한 인터페이스를 제공합니다.

일반적인 HTML 폼의 경우, 데이터를 표준 방식으로 인코딩할 필요가 있고, 그런 다음 data 인자로 Request 객체에 전달합니다. 인코딩은 urllib.parse 라이브러리의 함수를 사용하여 수행됩니다.

urlopen은 응답을 처리할 수 없을 때 URLError를 발생시킵니다. HTTPError는 HTTP URL의 특정 경우에 발생하는 URLError의 서브 클래스입니다. 예외 클래스는 urllib.error 모듈이 내보냅니다.

BeautifulSoup 은 HTML 및 XML 문서 를 구문 분석하기위한 Python 패키지입니다. HTML에서 데이터를 추출하는 데 사용할 수 있는 구문 분석된 페이지에 대한 구문 분석 트리를 만듭니다.

datetime은 날짜와 시간을 처리하는 모듈입니다. 여기서는 새롭게 추가되는 크롤링 데이터 위에 크롤링한 날짜와 시간을 함께 저장하기 위해 사용했다.

pandas는 자동적/명시적으로 축의 이름에 따라 데이터를 정렬할 수 있는 데이터구조이다. 잘못 정렬된 데이터에 의한 오류를 방지하고, 다양한 방식으로 색인된 데이터를 다룰 수 있는 기능이 있다. 여기서는 크롤링한 데이터를 엑셀파일로 저장하기 위해 사용했다.

url = 'https://news.naver.com'
html = urllib.request.urlopen(url).read()
bsObject = BeautifulSoup(html, 'html.parser')

네이버 뉴스 홈 화면의 주소를 url에 문자열로 담았다.
html은 네이버 뉴스 홈 화면의 html을 urllib.request의 urlopen() 함수를 이용해 가져오고 read() 함수를 통해 읽은 문서 전체를 담은 것이다.
bsObject는 html에 담긴 문자열은 단순한 텍스트가 아니라 html 구조에 맞게 작성되어있으니 html의 관점에서 이 문자열을 이해하게끔 한 것을 담은 것이다.

newslist = list()
nnews = list()
nlink = list()

my_news = bsObject.select(
'div#today_main_news > div.hdline_news > ul > li > div.hdline_article_tit'
)
my_news_link = bsObject.select(
'div[id=today_main_news] > div.hdline_news > ul > li > div.hdline_article_tit > a'
)

my_news는 html구조로 된 문자열 중에서 div.hdline_article_tit에 해당하는 내용을 담은 것이다. 여기서는 헤드뉴스의 타이틀에 해당하는 텍스트를 가져온 것이다.
my_news_link는 헤드라인 텍스트를 클릭했을 때 열리는 링크 주소를 담은 것이다.
여기서 div#today_main_news와 div[id=today_main_news]는 같은 것을 가리킨다. 즉 같은 뜻이고 표현만 달리한 것 뿐이다.

for news in my_news:
nnews.append(news.text.strip())

for link in my_news_link:
nlink.append("https://news.naver.com" + link.get('href'))

for i in range(len(nnews)):
newslist.append([nnews[i], nlink[i]])

for문을 이용해서 nnews와 nlink라는 list에 차례로 타이틀과 링크를 담았다. 그 후 각각 매치되는 타이틀과 링크를 newslist라는 list구조에 list형태로 담았다. 타이틀을 담을 때는 양 쪽에 공백이 있을 경우를 대비에 양 쪽 공백은 삭제 후 담는다.

time = datetime.today().strftime("%Y/%m/%d %H:%M:%S")

datetime모듈을 이용해 오늘 현재에 해당하는 시간을 time에 담는다. 이 때 YYYY/mm/dd HH:MM:SS 형태의 시간 출력하기 위해 strftime()를 이용한다.

data = pandas.DataFrame(newslist)
data.columns = [time + ' TITLE', 'LINK']
data.to_csv('news_headline.csv', mode = 'a', encoding='euc-kr')

pandas의 DataFrame() 함수를 이용해서 데이터틀을 형성하고 data에 담는다. data.columns는 newslist안에 담긴 각각의 list([타이틀,링크])에 해당하는 분류를 해주는 것이다. 그 후에 data.to_csv를 통해 엑셀파일로 저장되는데 파일명은 'news_headline.csv'가 되고 mode='a'는 크롤링하고 저장될 때마다 데이터가 쌓여서 저장되도록 함이다. encoding='euc-kr'은 엑셀파일에서 사용하는 code형태가 다르기 때문이다.

크롤링 후에 저장된 자료의 모습이다.

profile
BackEnd

0개의 댓글