구글 코랩(Colab)에서 멜론 시대별 차트 정보 크롤링 방법
오늘은 국내 대중가요 가사 텍스트 데이터를 이용하여 감정 분석을 진행할 목적으로
노래 정보를 파이썬으로 추출하였습니다.
구글 Colaboratory에서 동작하는 관련 소스코드를 공유합니다.
1. 추출하려는 노래 목록
- 멜론 > 멜론차트 > 시대 > 2023년도 1위 ~ 100위
- 해당 URL : https://www.melon.com/chart/age/index.htm?chartType=YE&chartGenre=KPOP&chartDate=2023&moved=Y&idx=1
2. 파이썬 소스코드
import re
import requests
from bs4 import BeautifulSoup
import pandas as pd
from time import sleep
import os
from tqdm import tqdm
# 2023년대 노래 시대별차트
headers = {
'User-Agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36')
}
age_url = "https://www.melon.com/chart/age/list.htm"
params = {
'idx': '1',
'chartType': 'YE', # 10년 단위로 검색하는 부분과 연관
'chartGenre': 'KPOP', # 가요검색: KPOP, 팝송검색: POP
'chartDate': '2023', # 검색연도
'moved': 'Y',
}
response = requests.get(age_url, params=params, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
song_list = soup.select('.lst50, .lst100')
# 데이터프레임 초기화
columns = ['chartDate', 'rank', 'title', 'singer', 'album_name', 'release_date', 'genre', 'lyric', 'composer', 'lyricist', 'arranger']
song_data = pd.DataFrame(columns=columns)
# tqdm 라이브러리로 진행 상황 바 표시
for i, meta in tqdm(enumerate(song_list, 1), total=len(song_list), desc="Processing songs"):
rank = i
try:
title = meta.select('a[href*=playSong]')[0].text
except:
title = meta.select('.wrap_song_info .ellipsis')[0].text
title = title.strip()
song_id_html = str(meta.select('a[onclick*=SongDetail]'))
matched = re.search(r"\'(\d+)\'", song_id_html)
song_id = matched.group(1)
song_url = 'https://www.melon.com/song/detail.htm?songId=' + song_id
response = requests.get(song_url, params=params, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
# 가수
singer_html = soup.select('.wrap_info .artist a')
singer_s = ', '.join([html['title'] for html in singer_html if html['title']]) if singer_html else 'Various Artists'
# 앨범명
album_name = soup.select('.list dd')[0].get_text(strip=True)
# 발매날짜
release_date = soup.select('.list dd')[1].get_text(strip=True)
# 장르
genre = soup.select('.list dd')[2].get_text(strip=True)
# 가사
lyric = '없음'
lyric_html = soup.select_one('.section_lyric .wrap_lyric .lyric')
if lyric_html:
lyric = lyric_html.get_text(strip=True, separator='\n')
# 작사, 작곡, 편곡
member_roles = {'작사': 'lyricist', '작곡': 'composer', '편곡': 'arranger'}
members = {v: '' for k, v in member_roles.items()}
for entry in soup.select('.section_prdcr .list_person .entry'):
role = entry.select_one('.meta').get_text(strip=True)
if role in member_roles:
members[member_roles[role]] = entry.select_one('.artist').get_text(strip=True)
# 데이터프레임에 추가
row = pd.Series([params['chartDate'], rank, title, singer_s, album_name, release_date, genre, lyric, members['composer'], members['lyricist'], members['arranger']], index=song_data.columns)
song_data = pd.concat([song_data, pd.DataFrame([row])], ignore_index=True)
sleep(1) # IP 차단 방지용
Subscribe
Login
0 Comments
Oldest