이 게시글은 데이터사이언스엔지니어링_전문가 과정을 수강하며 복습을 위해 정리한 글입니다.
네이버 뉴스 크롤링 세번째 게시글입니다. 앞선 게시글을 본 후 보는 것을 추천드립니다.
이제 드디어 본격적으로 기사 내용을 추출할 것이다.
원기사를 추출하기 앞서 간결하게 보이는 기사를 먼저 수집하려한다.
여기 보이는 기사들의 제목, 세부내용, 뉴스사, 날짜, url을 추출해 올 것이다.
from urllib.request import urlopen
import requests
import pandas as pd
import bs4 # 파싱패키지
def get_topic_info(url) :
# 빈 리스트 생성
paper_list = []
date_list = []
link_list = []
title_list = []
subscript_list = []
# 사이트(url)에 요청해서 소스 응답
headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.141 Whale/3.15.136.29 Safari/537.36"}
res = requests.get(url, headers=headers)
# bs4 객체 생성
html = res.text
bs_obj = bs4.BeautifulSoup(html,'html.parser')
try :
# 전체 기사 카드를 포함하고 있는 영역 추출
news_list = bs_obj.findAll("div",{'class':'cluster'})[1]
# news_list의 모든 li 태그 추출
lis = news_list.findAll('li')
for li in lis :
try :
title_list.append(li.findAll('a')[1].text)
link_list.append(li.findAll('a')[1]['href'])
subscript_list.append(li.find('span',{'class':'lede'}).text)
paper_list.append(li.find('span',{'class':'writing'}).text)
date_list.append(li.find('span',{'class':'date'}).text)
except :
print('이미지가 없음')
news_dict = {'제목':title_list,
'URL':link_list,
'신문사':paper_list,
'작성일':date_list,
'세부내용':subscript_list}
return news_dict
except :
print('형식이 조금 다름')
실행중에 대다수의 형식과 다른 기사들이 있어 오류가 발생할 수도 있다.
이 같은 경우 그 기사를 찾아서 따로 적용을 해주어도 되지만
지금 하는 크롤링의 경우 받아오는 데이터의 양이 많고 오류나는 기사 하나를 받아오지 않아도
전혀 문제가 되지 않기 때문에
그냥 예외처리하여 넘어가는 방법을 선택하였다.
꼭 모든 데이터를 받아와야 하는 경우에는 따로 코드를 만들기 바란다.
이제 위 함수를 사용해 데이터를 수집하여 저장해보겠다.
# 빈df 생성
dict_sub ={}
dict_sub["제목"] = []
dict_sub["URL"]=[]
dict_sub["신문사"] = []
dict_sub['작성일'] = []
dict_sub['세부내용'] = []
topic_info_df = pd.DataFrame(dict_sub)
topic_info_df
for url in topic_df['url'] :
res = pd.DataFrame(get_topic_info(url))
topic_info_df = pd.concat([topic_info_df,res],
axis=0,
ignore_index=True)
# 파일로 저장
topic_info_df.to_csv('./crawl_data/naver_news_topic_info.csv')
이제 마지막으로 최종수집된 토픽별 링크를 이용해서 원 기사 내용 정체를 수집할 것이다.
- 기사제목
- 기사입력시간
- 기사내용
- 함수로 구성 : get_news_sub_info(url)
이때 너무 많은 요청을 한번에 하면 접속거부될 수 있으므로 time.sleep()을 두고 텀을두고 진행하기 바란다.
def get_news_sub_info(url) :
dict_sub={}
# 1. 소스 추출
headers ={"User-Agent" :
"Mozilla/5.0(Window NT 10.0;Win64;x64) AppleWebKit/537.36 (KHTML,likeGecko) Chrome/87.0.4280.88 Safari/537.36"}
result = requests.get(url,headers=headers)
# 2. bs4 객체 생성
html = result.content
bs_obj = bs4.BeautifulSoup(html,'html.parser')
try :
# 3. 필요데이터 추출(parsing)
# 기사 제목
title = bs_obj.find("div",{'class':"media_end_head_title"}).text.replace('\n','')
# 기사 입력시간
date_time = bs_obj.find("div",{"class":"media_end_head_info_datestamp"}).find('span').text
# 기사 내용
contents = bs_obj.find(id='newsct_article').text
# 기사 저장
dict_sub['기사제목'] = title
dict_sub['기사입력시간'] = date_time
dict_sub['기사내용']= contents
return dict_sub
except :
print('error')
# 수집 데이터 불러오기
news_df = pd.read_csv('./crawl_data/naver_news_topic_info.csv', index_col=0)
news_df.head()
# 호출이 계속해서 들어오면 서버에서 공격으로 인지하고 접속을 끊어버리기 때문에
# 10개의 기사 데이터만 요청하겠다
df_url = news_df['URL'][2045:2055]
# 빈 데이터프레임 생성
dict_sub ={}
dict_sub["기사제목"] = []
dict_sub["기사입력시간"]=[]
dict_sub["기사내용"] = []
news_sub_df = pd.DataFrame(dict_sub)
news_sub_df
# 기사 추출
for url in df_url :
res = pd.DataFrame(get_news_sub_info(url),index=range(1,2))
news_sub_df = pd.concat([news_sub_df,res],axis=0,ignore_index=True)
# 파일로 저장
news_sub_df.to_csv('./crawl_data/naver_news.csv')
이렇게 하면 각 섹션별 토픽별 기사 크롤링이 완성된다!!
위의 방법을 따라 기사데이터 추출해 잘 사용하기 바란다.
크롤링 특성상 네이버가 페이지를 리뉴얼하면 위의 코드가 바로 적용되지 않을 수 있다.
하지만 방법을 알고 태그를 구별하여 대입한다면 충분히 크롤링할 수 있을것이다.
자세한 개념과 문법을 알고 싶다면 아래의 게시글로 가보길 바란다.
그럼 이만
'프로그래밍 > Crawling' 카테고리의 다른 글
[Selenium] 네이버 동적 로그인 하기 - 셀레니움 사용법 (0) | 2022.08.16 |
---|---|
[Python] Connection aborted에러 : Header추가하기 (크롤링) (0) | 2022.08.03 |
[WebCrawling] 네이버 뉴스 섹션 토픽 크롤링 2022.ver (0) | 2022.08.03 |
[WebCrawling] 네이버 뉴스 메뉴 크롤링 2022.ver (0) | 2022.08.03 |
[WebCrawling] 웹 크롤링 기본 개념 및 문법 (BeautifulSoup사용법) (0) | 2022.08.02 |