네이버 기사를 크롤링해보겠습니다.
전에 포스팅했던 '네이버 오픈 API 등록' 글에서 'Client ID'와 'Client Secret'을 가져옵니다.
https://kjws0712.tistory.com/100
네이버 오픈 API 등록
1. 구글 검색에 '네이버 개발자 API' 검색 2. 네이버 오픈 API 목록 클릭 3. 네이버 기사를 크롤링 하기 위해서는 검색 기사를 가져올 수 있어야 함으로 '검색' API 이용할 예정 4. 서비스 API 클릭 5. 검
kjws0712.tistory.com
import os
import sys
import urllib.request
client_id = "본인의 발급받은 Client ID" # 발급받은 client ID 작성
client_secret = "본인의 발급받은 Client Secret" # 발급받은 client secret 작성
encText = urllib.parse.quote("파이썬") # 검색할 단어
url = "https://openapi.naver.com/v1/search/news?query=" + encText # JSON 결과
# url = "https://openapi.naver.com/v1/search/blog.xml?query=" + encText # XML 결과
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id",client_id)
request.add_header("X-Naver-Client-Secret",client_secret)
response = urllib.request.urlopen(request) # 접속해준다
rescode = response.getcode() # 코드를 받아온다
if(rescode==200): # 200이면 정상,
response_body = response.read()
print(response_body.decode('utf-8'))
else:
print("Error Code:" + rescode) # 에러코드 출력
10, 11, 12번째 줄 request는 말 그대로 서버에 요청한다는 뜻입니다.
서버한테 이런 내용을 줘라.(어디에 접속할 지 URL, 정보를 줘야 함, 나는 API를 받았어, id와 secret)
요청한 URL을 승인 받으면 response변수는 요청한 URL을 접속해줍니다.
그리고 rescode변수를 통해 코드를 받아옵니다.
rescode가 200인 경우가 정상이라는 뜻입니다.
https://developers.naver.com/docs/serviceapi/search/news/news.md#%EB%89%B4%EC%8A%A4
검색 > 뉴스 - Search API
검색 > 뉴스 뉴스 검색 개요 개요 검색 API와 뉴스 검색 개요 검색 API는 네이버 검색 결과를 뉴스, 백과사전, 블로그, 쇼핑, 영화, 웹 문서, 전문정보, 지식iN, 책, 카페글 등 분야별로 볼 수 있는 API
developers.naver.com
위 링크를 참고하셔서 '응답 예', '오류 코드'를 보시면 좋으실 것 같습니다.
출력된 결과는 네이버 → 뉴스 → '파이썬' 검색시 나오는 최신순 기사입니다.
위 코드의 단점은 본문 API를 제공하지 않아서 본문 내용을 가져올 수가 없습니다.
그래서 본문 내용을 가져오기 위해선 따로 접속해서 가져와야 합니다.
import os
import sys
import urllib.request
import requests
news_data = [] # 딕셔너리 형태
client_id = "발급받은 Client ID"
client_secret = "발급받은 Client Secret" # 발급받은 client secret
encText = urllib.parse.quote("파이썬") # 검색할 단어
url = "https://openapi.naver.com/v1/search/news?query=" + encText # JSON 결과
# url = "https://openapi.naver.com/v1/search/blog.xml?query=" + encText # XML 결과
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id",client_id)
request.add_header("X-Naver-Client-Secret",client_secret)
response = urllib.request.urlopen(request) # 접속해준다
rescode = response.getcode() # 코드를 받아온다
if (rescode==200):
result = requests.get(response.geturl(),
headers = {"X-Naver-Client-Id":client_id,
"X-Naver-Client-Secret":client_secret}
)
news_data.append(result.json()) # 딕셔너리 형태로 저장
else:
print("Error Code:" + rescode)
# 네이버 OPEN API를 통해 가져온 데이터 확인하기
news_data
첫 번째 코드는 단지 print만 수행했지만, 불러온 내용을 사용해야 함으로 저장코드가 필요하기 때문에 두 번째 코드를 작성하였습니다.
request.get은 요청하면 받아온다는 뜻이고, json은 파이썬 입장에서는 key, value를 뜻합니다.
news_data[0]['items'][0]['link']
# print(news_data[0]['items'][0]['link'])
# print 함수를 사용하면 바로 url을 통해 접속 가능
'http://www.veritas-a.com/news/articleView.html?idxno=450711'
모든 기사의 태그가 달라서 모든 기사를 가져올 수는 없습니다. 일일이 직접 가져와야하는데 시간적 번거로움이 발생합니다. 네이버 뉴스 기사가 통계적으로 많아서 네이버 뉴스만 가져오는게 효과적입니다.
가져온 URL이 네이버 뉴스인지 확인해보겠습니다.
page_news_link = []
for item in news_data[0]['items']:
link = item['link']
if "naver" in link:
page_news_link.append(link)
len(page_news_link) # 페이지 링크 안에 네이버 뉴스는 2개, 현재시간 기준이므로 다시 할 시 바뀜
2
현 시간에 네이버 뉴스 검색창에 "파이썬"을 검색하면 네이버 뉴스는 2개가 존재합니다.
여러 페이지 기사 가져오기
한 페이지에 10개의 기사만 존재하고, 그 중에서 네이버 뉴스는 2개만 존재하였습니다.
이번에는 여러 페이지를 가져와 보겠습니다.
뉴스 1페이지에 URL 링크를 보면 Start=1이라는 점을 참고하면서 진행하겠습니다.
한 페이지에 기사가 10개 존재함으로, 뉴스 2페이지에서는 Start=11입니다.
import os
import sys
import urllib.request
import requests
news_data = [] # 딕셔너리 형태
page_count = 3 # 3페이지만 가져오기 위해
client_id = "발급받은 Client ID"
client_secret = "발급받은 Client Secret" # 발급받은 client secret
encText = urllib.parse.quote("파이썬") # 검색할 단어
for idx in range(page_count):
url = "https://openapi.naver.com/v1/search/news?query=" + encText + "&start=" + str(idx*10+1) # JSON 결과
# url = "https://openapi.naver.com/v1/search/blog.xml?query=" + encText # XML 결과
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id",client_id)
request.add_header("X-Naver-Client-Secret",client_secret)
response = urllib.request.urlopen(request) # 접속해준다
rescode = response.getcode() # 코드를 받아온다
if (rescode==200):
result = requests.get(response.geturl(),
headers = {"X-Naver-Client-Id":client_id,
"X-Naver-Client-Secret":client_secret}
)
news_data.append(result.json()) # 딕셔너리 형태로 저장
else:
print("Error Code:" + rescode)
2번째 코드와 다른 점은 news_data 딕셔너리를 생성하였고, 3페이지만 가져오기 위해 page_count를 3으로 지정했습니다.
for문을 활용하여 1, 2, 3페이지별 URL을 지정하였습니다.
1페이지의 Start=1이라는 점을 이용하여 코드를 알맞게 설정하였습니다.
news_data[0]['items'][0]['link']
'https://n.news.naver.com/mnews/article/092/0002286288?sid=105'
크롤링한 1페이지의 첫번째 기사의 URL 주소입니다.
news_data
살펴보면 3개의 딕셔너리가 존재하고 각 딕셔너리의 'start' key값을 보면 1, 11, 21을 확인할 수 있습니다.
페이지 별 네이버 기사 수 가져오기
지정한 페이지 수 별로 네이버 기사만 가져오는 코드를 작성해보겠습니다.
naver_news_link = [] # 페이지 별 네이버 기사 수
for page in news_data:
page_news_link = []
for item in page['items']:
link = item['link']
if "naver" in link:
page_news_link.append(link)
naver_news_link.append(page_news_link)
for page in naver_news_link:
for link in page:
print(link) # 링크 다 나옴, 총 8개 기사 있음
print(naver_news_link) # 각 페이지별 기사 URL
print(len(naver_news_link)) # 3페이지, 3
이 코드는 딱히 설명드릴점이 없으니 눈으로 보고 한번 작성해보심이 좋을 듯 싶습니다.
크롤링하는데 필요한 모듈과 패키지
import pandas as pd
import numpy as np
from selenium import webdriver
from tqdm import tqdm_notebook
import requests
import pickle
import re
import ast
from bs4 import BeautifulSoup
from urllib.request import urlopen
import urllib
import time
# 가상 크롬드라이버를 불러옴
# 윈도우 10의 경우 chromedriver.exe
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome('chromedriver')
크롤링하는데 필요한 모듈과 패키지를 적어보았습니다.
selenium과 BeautifulSoup가 중요합니다.
가상 크롬드라이버를 만드는 이유는 컴퓨터에 있는 크롬이 가상환경에서는 적용되지 않더라고요...(맞는지는 잘 모르겠지만 그럴거 같네요..뇌피셜입니다)
이제 한 코드블록으로 원하는 기사 링크의 제목, 본문 내용을 크롤링 해보겠습니다.
# https://n.news.naver.com/mnews/article/092/0002286288?sid=105
# 위 링크 기사를 크롤링 함
naver_news_title = []
naver_news_content = []
for n in tqdm_notebook(range(len(naver_news_link))):
#print(n)
news_page_title = []
news_page_content = []
for idx in tqdm_notebook(range(len(naver_news_link[n]))):
########### 긁어온 URL로 접속하기 ############
try:
driver.get(naver_news_link[n][idx])
print(naver_news_link[n][idx])
except:
print("Timeout!")
continue
try:
response = driver.page_source
except UnexpectedAlertPresentException: # 게시글이 삭제된 경우
driver.switch_to_alert().accept()
print("게시글이 삭제된 경우입니다.")
continue
soup = BeautifulSoup(response, "html.parser")
###### 뉴스 타이틀 긁어오기 ######
title = None
try:
item = soup.find('div', class_="media_end_head_title")
title = item.find('h2', class_="media_end_head_headline").get_text()
#print(title)
except:
title = "OUTLINK"
#print(title)
news_page_title.append(title)
###### 뉴스 본문 긁어오기 ######
doc = None
text = ""
data = soup.find_all("div", {"class" : "go_trans _article_content"}) # 그림, 텍스트 다 가져옴
if data:
for item in data:
text = text + str(item.find_all(text=True)).strip() # 텍스트만 가져옴
text = ast.literal_eval(text) # 어려운 코드, skip, 안정적임
doc = ' '.join(text)
else:
doc = "OUTLINK"
news_page_content.append(doc.replace('\n', ' '))
naver_news_title.append(news_page_title)
naver_news_content.append(news_page_content)
time.sleep(2) # DDOS로 인식해서 막아버림
print(naver_news_title[0])
print("==================================")
print(naver_news_content[0])
※ 뉴스 타이틀과 뉴스 본문의 'div', 'class', 'h2', 'h3'등이 다를 수 있으므로 해당 기사 페이지에 들어가서 제목과 내용에서 오른쪽 누르고 '검사'를 클릭 후 확인하시고 알맞게 사용하셔야 합니다.
naver_news_title과 naver_news_content 리스트를 생성하고, try문을 활용합니다.
- 우선 긁어온 URL로 접속하고
- 뉴스 타이틀을 긁어옵니다.
- 뉴스 본문을 긁어옵니다.
- time.sleep을 적용합니다.
print(naver_news_title)
[['AI 챗GPT가 개발자들의 미래에 미치는 영향은?', '허깅페이스, 자바스크립트용 기계학습 라이브러리 공개', '한국경영인증원(KMR), 도봉구와 빅데이터 분석 입문 무료교육 진행'], ['지역 청년 위한 인턴십 프로그램 확대', '메타버스로 일 배운다…리모트 인턴십 확대 운영', 'CJ올리브네트웍스, 지역청년 인턴십 확대'], ['CJ올리브네트웍스, 지역거점 청년 위한 리모트인턴십 확대 운영', 'CJ올리브네트웍스, 지역거점 청년 위한 ‘리모트 인턴십’ 확대 \xa0']]
naver_news_title을 보면 총 3페이지에 있는 네이버 뉴스 기사 제목 8개가 나타납니다.
print(naver_news_content)
naver_news_title을 보면 총 3페이지에 있는 네이버 뉴스 기사 원본 8개가 나타납니다.
크롤링 결과 저장 (pickle)
이제 크롤링한 결과를 저장해보겠습니다. pickle을 이용해보겠습니다.
with open("naver_news_title.pk", "wb") as f:
pickle.dump(naver_news_title, f)
with open("naver_news_content.pk", "wb") as f:
pickle.dump(naver_news_content, f)
디렉토리를 확인해보면, naver_news_title.pk와 naver_news_content.pk가 저장되었습니다.
'PROJECT > 텍스트 마이닝을 활용하여 문자 대화내용 분석' 카테고리의 다른 글
konlpy 형태소 분석기 성능비교 (0) | 2023.03.27 |
---|---|
기사 텍스트 정제 - konlpy 설치 (WINDOWS) (0) | 2023.03.24 |
네이버 오픈 API 등록 (0) | 2023.03.20 |
텍스트 마이닝 - 워드 임베딩 (0) | 2023.03.20 |
텍스트 마이닝 - 텍스트 시각화 (0) | 2023.03.18 |