| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- #abc 프로젝트 멘토링 #유클리드소프트 #고용노동부 #대한상공회의소 #미래내일일경험사업 #공부일지 #멘토링일지
- #abc부트캠프 #유클리드소프트 #고용노동부 #대한상공회의소 #미래내일일경험사업
- Today
- Total
나른한 코딩 생활
[11일차] ABC 부트캠프 데이터 크롤링 실전 본문
이번주차부터는 실제로 데이터 크롤링을 해보면서 기초를 기르고
여러가지 매체에서 원하는 데이터를 수집해 보는 작업을 해볼 것이다.
오늘은 네이버 랭킹뉴스에서 얼론사별 데이터를 수집하고 시각화 하는 작업을 해보자
인터넷과 HTML 기초
인터넷 관련 용어
`IP 주소`
인터넷에 연결된 모든 컴퓨터에 부여되는 고유의 식별 주소를 의미한다
`도메인 이름 Domain Name`
IP 주소의 별칭이라고 생각하면 편함
just like 집주소
`URL Uniform Resource Locator`
ex ) ‘프로토콜://정보를 가진 컴퓨터 이름/디렉터리 이름/파일명’
`HTTP (HyperText Transfer Protocol)`
통신 규약 중 하나
'http://www...' 와 같이 하는 것
https : security 서버
문서화 언어
총 3개 SGML , HTML, XML
SGML : 정해진 구조
HTML : 커스텀
XML : SGML + HTML
HTML 기본구조
- 태그를 열었으면 끝날 때 닫아라
- <태그명> ... </태그명>
- <head.> 태그 안에 화면에 대한 설명
- <body.> 문서 정보가 담김
글자/문단/목록 태그와 링크 태그
글자 태그
`<Hn> 태그`
`<FONT>태그`
잘 안쓴다고 함
문단 태그
`<DIV>태그`
특정 파트만 수집하고 싶다 하는데 해당 구역이 DIV 태그 안에 나눠져 있을 수 있음
목록 태그
- 지금 이런
- 형태와 비슷한
- 태그가 목록 태그
`<OL>태그`
하이퍼링크 태그
`<A>태그`
문서, 사이트들 이동가능
`<A href= ~ >`
href 속성 : 페이지로 이동할 수 있게 도와주는 태그
멀티미디어 태그와 테이블 태그
요즘에는 굉장히 사용안함
이미지 , 동영상 등의 태그
이미지 태그
`<IMG src>`
src : sorce 의 약자
실제 어디있는 이미지인지를 알려줌
테이블 태그
테이블로 정렬하게 하는 태그
(자바의 컨테이너와 비슷해보임)
프레임 태그와 입력 태그
프레임 태그
입력 태그
`<INPUT> 태그`
`<INPUT type="text" ~ >` : 텍스트박스 형식의 인풋태그
`<INPUT type = "raido" ~ >` : 라디오 버튼 형식의 인풋태그
`<INPUT type = "checkbox" ~ >` : 체크박스 형식의 인풋태그
팝업 메뉴 & 리스트박스
TEXTAREA 태그
CSS (Cascading Style Sheet)
크롤링의 키 포인트 !
예쁜 홈피 만들기의 기초
개발자와 디자이너의 작업 환경을 불리시켜 나온 스타일 시트
CSS의 이해
CSS 정의 방법
클래스 선택자
예쁜 옷을 입힐려고 쓰는태그
특정 태그를 골라내는 방법?
- CLASS 를 다르게 입혀 원하는 태그의 자료를 크롤링 할 수 있음
ID 선택자
클래스 선택자와 유사하지만 화면 하나에 한번만 기술 할 수 있도록 함
즉, 한 문서에 한번만 사용할 수 있다는 차이점이 존재
태그가 아이디도 있고 클래스 도 있으면 ID 로 추출하면 더 정확하게 해당 정보를 가져올 수 있다.
그 외
동적 정적
마우스 우클릭 -> 페이지 소스 보기 하고
동적 : HTML 태그가 보이지 않음
정적 : 화면 안에 태그등의 정보가 보임
html 들어가있는 정보가 없을 수 있다
확인 후 정보가 있으면 -> 정적 -> 코랩에서 크롤링 가능
정보가 없으면 -> 동적 -> 아나콘다를 통해 스파이더 툴 사용 ( 어려움 )
코랩으로 데이터 수집
데이터 시간이 중요하다
datetime 은 미국시간 기준
위에서 아래로 데이터 수집
-> 데이터 수집 순서를 잘 정해야함
크롤링할때의 핵심 중 하나
'keep going'
하나의 오류로 했던 크롤링들을 망치면 시간이 너무 낭비된다
오류가 나더라도 다음 자료, 또는 다음 페이지 등으로 예외처리 후 넘어가는게 필요하다
네이버 언론사별 랭킹 뉴스 데이터 수집 및 시각화
패키지 인스톨 및 임포트
!pip install konlpy
!pip install koreanize-matplotlib
from urllib.request import urlopen
from bs4 import BeautifulSoup # 태그로 정보를 추출할떄 (파씽할때) 사용함
import pandas as pd
import datetime
from pytz import timezone # datetime은 미국 시간이기 때문에 timezone을 통해 대한민국 시간 가져오기
import warnings
warnings.filterwarnings('ignore')
# -- 데이터 시각화 --
import matplotlib.pyplot as plt
import seaborn as sns
import koreanize_matplotlib
import konlpy
from wordcloud import WordCloud
많이 본 뉴스 크롤링
기본적인 임포트가 끝났으면 이제 본격적인 크롤링의 시작이다
# 1) 데이터 프레임 생성
data = pd.DataFrame(columns=['언론사명','순위','기사제목','기사링크','수집일자'])
# 2) 네이버 언론사별 랭킹 뉴스 URL
url = 'https://news.naver.com/main/ranking/popularDay.naver'
# 3) url 접속하여 html 가져오기
html = urlopen(url)
# 4) HTML 태그 파싱하여 변환
soup = BeautifulSoup(html, 'html.parser') # html parser 규칙으로 파싱한다
# 5) 네이버 랭킹 정보가 있는 div만 추출 -> rankingnews_box 가져오기
div = soup .find_all('div',{'class': 'rankingnews_box'})
#find_all 은 해당 박스를 다 가져옴 / find 는 하나만 찾음
# print(len(div)) 랭킹뉴스 박스만 80개
# 6) 네이버 랭킹 언론사명, 기사제목 등 데이터 수집
for index_div in range(0,len(div)):
# 언론사명 추출
strong = div[index_div].find('strong',{'class':'rankingnews_name'}) # 최초의 태그가 통째로 담긴다
press = strong.text # 안의 값을 press에 넣는다
# 5개의 순위 기사 정보 추출
ul = div[index_div].find_all('ul',{'class':'rankingnews_list'})
for index_r in range(0, len(ul)):
li = ul[index_r].find_all('li')
for index_l in range(0,len(li)):
try:
rank = li[index_l].find('em',{'class':'list_ranking_num'}).text
title = li[index_l].find('a').text
link = li[index_l].find('a').attrs['href'] # href 속성을 가지고 있는 애들만 가져온다
# 임시(Temporaly) DataFrame
temp_df = pd.DataFrame({'언론사명':press,
'순위':rank,
'기사제목':title,
'기사링크':link,
'수집일자':datetime.datetime.now(timezone('Asia/Seoul'))},
index=['순위'])
# print(temp_df)
data = pd.concat([data,temp_df],ignore_index=True)
except:
pass # try except 는 실제 데이터를 수집하는 구간에서 사용하는 것이 좋음 ( 예외처리 )
print('Complets of ' + rank + ' : ' + title)
print('-'*50)
print(data.info())
이후에 data 에 대한 이상이 없는지 tail 과 head 함수를 사용하여 데이터 검사를 실시한다.

data.to_csv('네이버랭킹뉴스_많이본뉴스_20240708.csv',encoding='utf-8-sig',index=False)
이후 데이터를 혹시 모를 상황에 대비해 배업 및 크롤링한 자료를 중간중간 백업한다
수집한 데이터 시각화
다음은 워드 클라우드를 위한 텍스트 전처리와 시각화 과정이다.
# 기사 제목을 활용한 워드 클라우드 -> text(텍스트 뭉치) 형태로 변환
text = ' '.join(li for li in data['기사제목'].astype(str)) # object 형태이기 때문에 str 형태로 변환함
# 워드 클라우드 시각화
font_path = '/content/BMDOHYEON_ttf.ttf'
plt.subplots(figsize=(25, 15))
wc=WordCloud(width=1000, height=700, font_path=font_path).generate(text)
plt.axis('off') # 눈금을 삭제시켜 차트를 이미지형식으로 보이게
plt.imshow(wc,interpolation='bilinear')
plt.show()

많이 본 뉴스와 댓글이 많은 뉴스 비교
이번에는 위에 코드를 참고하여 data, text 변수를 각각 re_data, re_text로 바꾼뒤
url 을 네이버 댓글 랭킹 순으로 바꾸어준다.
# 1) 데이터 프레임 생성
re_data = pd.DataFrame(columns=['언론사명','순위','기사제목','기사링크','수집일자'])
# 2) 네이버 언론사별 랭킹 뉴스 URL - 댓글이 많은 뉴
url = 'https://news.naver.com/main/ranking/popularMemo.naver'
# 3번 이후는 re_data 에 대한 코드로 모두 같게 실행한다
re_text = ' '.join(li for li in re_data['기사제목'].astype(str))
전처리 과정이 끝나면 이제 두 개의 워드 클라우드를 한 화면에 띄운 다음 비교해보자
fig = plt.figure(figsize=(15,5))
rows = 1
cols = 2
ax1 = fig.add_subplot(rows, cols, 1)
ax1.imshow(wc,interpolation='bilinear')
ax1.set_title('언론사별 많이 본 뉴스')
ax1.axis('off')
ax2 = fig.add_subplot(rows, cols, 2)
ax2.imshow(re_wc,interpolation='bilinear')
ax2.set_title('언론사별 댓글이 많은 뉴스')
ax2.axis('off')
plt.show()

네이버TV연예 공감별 랭킹 뉴스 데이터 수집 및 시각화
새로운 노트북파일에(코랩) 이번에는 네이버 TV 연예 랭킹 뉴스 탭에서 공감별 데이터를 수집 및 시각화 해보자
패키지 설치 및 임포트 과정은 동일 하므로 넘어가겠다
- https://entertain.naver.com/ranking/sympathy
- https://entertain.naver.com/ranking/sympathy/cheer
- https://entertain.naver.com/ranking/sympathy/congrats
- https://entertain.naver.com/ranking/sympathy/expect
- https://entertain.naver.com/ranking/sympathy/surprise
- https://entertain.naver.com/ranking/sympathy/sad
랭킹 :: 네이버 TV연예
지금 가장 핫한 연예 이야기
entertain.naver.com
크롤링 하는 사이트들은 다음과 같다
위에서 부터 [ 좋아요 응원해요 축하해요 기대해요 놀랐어요 슬퍼요 ] 순으로 되어있다.
# 1) 데이터 프레임 생성
data = pd.DataFrame(columns=['순위', '공감종류', '기사제목', '기사링크', '기사내용', '공감수', '수집일자'])
# 2) 네이버 TV연예 랭킹 뉴스 URL
# https://entertain.naver.com/ranking/sympathy
# https://entertain.naver.com/ranking/sympathy/cheer
# https://entertain.naver.com/ranking/sympathy/congrats
# https://entertain.naver.com/ranking/sympathy/expect
# https://entertain.naver.com/ranking/sympathy/surprise
# https://entertain.naver.com/ranking/sympathy/sad
url_list = ['', '/cheer', '/congrats','/expect','/surprise','/sad']
for n in url_list:
# 공감별 url 준비
url = 'https://entertain.naver.com/ranking/sympathy' + n
print(url)
# 공감 종류
sympathy = 'love'
if n != '': # n이 비어있지 않으면
sympathy = n.replace('/', '')
# 3) html 가져오기
html = urlopen(url)
# 4) url 접속하여 html 가져오기
soup = BeautifulSoup(html, 'html.parser')
# 5) 랭킹 정보가 있는 li 만 추출 -> _inc ~ reply 가져오기
li = soup.find_all('li',{'class':'_inc_news_lst3_rank_reply'})
# 6) 네이버 연예 랭킹 30위 데이터 수집
for index_l in range(0,len(li)):
rank = li[index_l].find('em',{'class':'blind'}).text
# 뉴스 제목
title = li[index_l].find('a',{'class':'tit'}).text
# 뉴스 내용
summary = li[index_l].find('p',{'class':'summary'}).text
# 뉴스 링크
link = li[index_l].find('a').attrs['href']
# 공감수
temp_cnt = li[index_l].find('a',{'class':'likeitnews_item_likeit'}).text.replace('\n','') # 공백 삭제를 위한 replace
# likeitnews_item_likeit like 의 공백 뒤의 like는 없어도 됨
cnt = re.sub('[^0-9]','', temp_cnt) # 패키지함수 // ('[^0-9]') -> 숫자 제외 모두 삭제
# [] -> 정규식 규격 / ^ -> 아닌 애들 / , '' -> 찾아서 없애 / temp_cnt -> 여기에서
temp_df = pd.DataFrame({'순위':rank,'공감종류':sympathy,
'기사제목':title,'기사링크':link,
'기사내용':summary,'공감수':cnt,
'수집일자':datetime.datetime.now(timezone('Asia/Seoul'))},
index=['순위'])
data = pd.concat([data,temp_df],ignore_index=True)
print('Complets of ' + rank + ' : ' + title)
print('-'*50)
print(data.info())
input_sympathy = input('보고 싶은 공감 랭킹 뉴스를 입력하세요' + str(data['공감종류'].unique().tolist()))
text = ' '.join(li for li in data[data['공감종류']==input_sympathy].기사제목.astype(str))
font_path = '/content/BMDOHYEON_ttf.ttf'
plt.subplots(figsize=(25, 15))
wc=WordCloud(width=1000, height=700, font_path=font_path).generate(text)
plt.axis('off') # 눈금을 삭제시켜 차트를 이미지형식으로 보이게
plt.imshow(wc,interpolation='bilinear')
plt.show()


내일은 유튜브 댓글 크롤링하는 정적 크롤링에 대해 알아보도록 하자
'ABC 부트캠프' 카테고리의 다른 글
| [13일차] ABC 부트캠프 멜론 연간 TOP30 차트 추출 (0) | 2024.07.13 |
|---|---|
| [12일차] ABC 부트캠프 유튜브 댓글 크롤링 (5) | 2024.07.10 |
| [10일차] ABC 부트캠프 ESG포럼&세미나 (0) | 2024.07.07 |
| [9일차] ABC 부트캠프 도로교통공단 데이터로 종합적인 데이터 분석 (0) | 2024.07.04 |
| [8일차] ABC 부트캠프 라이브러리를 통한 데이터 분석 (0) | 2024.07.03 |