Web Crawling: 멜론 차트로 연습하기

코드싸개·2021년 1월 7일
1

Play with Data

목록 보기
1/2

태그 속성 확인하기

from selenium import webdriver
driver = webdriver.Safari()
url = 'https://www.naver.com'
driver.get(url)
html = driver.page_source
# 예제 2-40 실습용 HTML
html = '''
<html>
    <head>
    </head>
    <body>
        <h1> 우리동네시장</h1>
            <div class = 'sale'>
                <p id='fruits1' class='fruits'>
                    <span class = 'name'> 바나나 </span>
                    <span class = 'price'> 3000원 </span>
                    <span class = 'inventory'> 500개 </span>
                    <span class = 'store'> 가나다상회 </span>
                    <a href = 'http://bit.ly/forPlaywithData' > 홈페이지 </a>
                </p>
            </div>
            <div class = 'prepare'>
                <p id='fruits2' class='fruits'>
                    <span class ='name'> 파인애플 </span>
                </p>
            </div>
    </body>
</html>
'''
from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

태그명이 span 인 태그와 p 인 태그를 변수에 저장

tags_span = soup.select('span')
tags_p = soup.select('p')

아이디 값이 fruits1인 태그를 모두 ids_fruits1에 저장
class 명이 price인 태그를 모두 class_price에 저장
태그명이 span이면서 class명이 price인 태그를 모두 저장

ids_fruits1 = soup.select('#fruits1')
class_price = soup.select('.price')
tags_span_class_price = soup.select('span.price')
print(ids_fruits1)
print('-'*40)
print(class_price)
print('-'*40)
print(tags_span_class_price)
print('-'*40)
print(type(ids_fruits1))
[<p class="fruits" id="fruits1">
<span class="name"> 바나나 </span>
<span class="price"> 3000원 </span>
<span class="inventory"> 500개 </span>
<span class="store"> 가나다상회 </span>
<a href="http://bit.ly/forPlaywithData"> 홈페이지 </a>
</p>]
----------------------------------------
[<span class="price"> 3000원 </span>]
----------------------------------------
[<span class="price"> 3000원 </span>]
----------------------------------------
<class 'bs4.element.ResultSet'>

상위 구조 활용하기

태그의 속성만으로 정보를 찾기 힘들 때, 어떠한 부모 태그 아래에 있는지 등을 추가해서 검색할 수 있다. 이때 '>' 기호를 사용한다.

tags_name = soup.select('span.name')
print(tags_name)
[<span class="name"> 바나나 </span>, <span class="name"> 파인애플 </span>]

이때 바나나만 뽑아내고 싶으면 부모 태그 정보를 추가한다.

tags_banana1 = soup.select('#fruits1 > span.name')
print(tags_banana1)
[<span class="name"> 바나나 </span>]
tags_banana2 = soup.select('div.sale > #fruits1 > span.name')
tags_banana3 = soup.select('div.sale span.name')
print(tags_banana2)
print(tags_banana3)
[<span class="name"> 바나나 </span>]
[<span class="name"> 바나나 </span>]

위와 같이 '>' 기호와 띄어쓰기를 이용해서 원하는 태그를 찾을 수 있다.

태그 그룹에서 하나의 태그 선택하기

tags = soup.select('span.name')
tag_1 = tags[0]
print(tags)
print(tag_1)
[<span class="name"> 바나나 </span>, <span class="name"> 파인애플 </span>]
<span class="name"> 바나나 </span>
tags = soup.select('span.name')
for tag in tags:
    print(tag)
<span class="name"> 바나나 </span>
<span class="name"> 파인애플 </span>

선택한 태그에서 정보 가져오기

브라우저 화면에 표시되는 정보 수집할때: .text
URL 주소 수집할때: ['href']

tags = soup.select('a')
tag = tags[0]
contect = tag.text
print(contect)
link = tag['href']
print(link)
 홈페이지 
http://bit.ly/forPlaywithData

멜론 노래 순위 정보 크롤링

멜론 사이트

driver = webdriver.Safari()
url = 'https://www.melon.com/chart/index.htm'
driver.get(url)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')

노래의 정보를 가져오는 방법은 BeautifulSoup을 이용하는 방법과 selenium을 이용하는 것 두 종류가 있다.

songs = soup.select('table > tbody > tr')
# driver.find_elements_by_css_selector('table > tbody > tr')
print(len(songs))
print(songs[0])
100
<tr data-song-no="33077590">
<td><div class="wrap t_right"><input class="input_check" name="input_check" title="VVS (Feat. JUSTHIS) (Prod. GroovyRoom) 곡 선택" type="checkbox" value="33077590"/></div></td>
<td><div class="wrap">
<a class="image_typeAll" href="javascript:melon.link.goAlbumDetail('10521601');" title="쇼미더머니 9 Episode 1">
<img alt="쇼미더머니 9 Episode 1 - 페이지 이동" height="60" onerror="WEBPOCIMG.defaultAlbumImg(this);" src="https://cdnimg.melon.co.kr/cm2/album/images/105/21/601/10521601_20201120125511_500.jpg/melon/resize/120/quality/80/optimize" width="60"/>
<span class="bg_album_frame"></span>
</a>
</div></td>
<td><div class="wrap">
<a class="btn button_icons type03 song_info" href="javascript:melon.link.goSongDetail('33077590');" title="VVS (Feat. JUSTHIS) (Prod. GroovyRoom) 곡정보"><span class="none">곡정보</span></a>
</div></td>
<td><div class="wrap">
<div class="wrap_song_info">
<div class="ellipsis rank01"><span>
<a href="javascript:melon.play.playSong('19030101',33077590);" title="VVS (Feat. JUSTHIS) (Prod. GroovyRoom) 재생">VVS (Feat. JUSTHIS) (Prod. GroovyRoom)</a>
</span></div>
<br/>
<div class="ellipsis rank02">
<a href="javascript:melon.link.goArtistDetail('2866523');" title="미란이 (Mirani) - 페이지 이동">미란이 (Mirani)</a>, <a href="javascript:melon.link.goArtistDetail('2747971');" title="먼치맨 - 페이지 이동">먼치맨</a>, <a href="javascript:melon.link.goArtistDetail('1703507');" title="Khundi Panda - 페이지 이동">Khundi Panda</a>, <a href="javascript:melon.link.goArtistDetail('2745413');" title="머쉬베놈 (MUSHVENOM) - 페이지 이동">머쉬베놈 (MUSHVENOM)</a><span class="checkEllipsis" style="display: none;"><a href="javascript:melon.link.goArtistDetail('2866523');" title="미란이 (Mirani) - 페이지 이동">미란이 (Mirani)</a>, <a href="javascript:melon.link.goArtistDetail('2747971');" title="먼치맨 - 페이지 이동">먼치맨</a>, <a href="javascript:melon.link.goArtistDetail('1703507');" title="Khundi Panda - 페이지 이동">Khundi Panda</a>, <a href="javascript:melon.link.goArtistDetail('2745413');" title="머쉬베놈 (MUSHVENOM) - 페이지 이동">머쉬베놈 (MUSHVENOM)</a></span>
</div>
<div class="wrap_atist" style="">
<button class="button_icons etc more_down" data-control="dropdown" title="아티스트 더보기" type="button"><span class="none">아티스트명 더보기</span></button>
<div class="atist_view" style="display:none;">
<ul>
<li><a class="ellipsis" href="javascript:melon.link.goArtistDetail('2866523');" title="미란이 (Mirani) 페이지 이동">미란이 (Mirani)</a></li>
<li><a class="ellipsis" href="javascript:melon.link.goArtistDetail('2747971');" title="먼치맨 페이지 이동">먼치맨</a></li>
<li><a class="ellipsis" href="javascript:melon.link.goArtistDetail('1703507');" title="Khundi Panda 페이지 이동">Khundi Panda</a></li>
<li><a class="ellipsis" href="javascript:melon.link.goArtistDetail('2745413');" title="머쉬베놈 (MUSHVENOM) 페이지 이동">머쉬베놈 (MUSHVENOM)</a></li>
</ul>
</div>
</div>
</div>
</div></td>
<td><div class="wrap">
<div class="wrap_song_info">
<div class="ellipsis rank03">
<a href="javascript:melon.link.goAlbumDetail('10521601');" title="쇼미더머니 9 Episode 1 - 페이지 이동">쇼미더머니 9 Episode 1</a>
</div>
</div>
</div></td>
<td><div class="wrap">
<button class="button_etc like" data-song-menuid="19030101" data-song-no="33077590" title="VVS (Feat. JUSTHIS) (Prod. GroovyRoom) 좋아요" type="button"><span class="odd_span">좋아요</span>
<span class="cnt">
<span class="none">총건수</span>
151,647</span></button>
</div></td>
<td><div class="wrap t_center">
<button class="button_icons play" onclick="melon.play.playSong('19030101',33077590);" title="듣기" type="button"><span class="none">듣기</span></button>
</div></td>
<td><div class="wrap t_center">
<button class="button_icons scrap" onclick="melon.play.addPlayList('33077590');" title="담기" type="button"><span class="none">담기</span></button>
</div></td>
<td><div class="wrap t_center">
<button class="button_icons download" onclick="melon.buy.goBuyProduct('frm', '33077590', '3C0001', '','0', '19030101');" title="다운로드" type="button"><span class="none">다운로드</span></button>
</div></td>
<td><div class="wrap t_center">
<button class="button_icons video disabled" disabled="disabled" onclick="melon.link.goMvDetail('19030101', '33077590','song');" title="뮤직비디오" type="button"><span class="none">뮤직비디오</span></button>
</div></td>
</tr>

len() 의 결과가 100 이므로 1위부터 100위의 곡 수와 일치한다. 이번엔 먼저 1위 곡의 노래 제목과 가수를 찾아서 반복문으로 100곡의 제목과 가수를 찾아보자.

song = songs[0]
title = song.select('a')
len(title)
16

태그명이 a인 태그가 16개인데 이 중 곡 제목이 포함된 태그만 가져오려면 조건을 추가해야한다.

title = song.select('span > a')
len(title)
5

아직도 5개가 나오므로 조건을 더 추가하자.

title = song.select('div.ellipsis.rank01 > span > a')
len(title)
1
title
[<a href="javascript:melon.play.playSong('19030101',33077590);" title="VVS (Feat. JUSTHIS) (Prod. GroovyRoom) 재생">VVS (Feat. JUSTHIS) (Prod. GroovyRoom)</a>]

이제 여기서 title 부분만 추출하자.

title = song.select('div.ellipsis.rank01 > span > a')[0].text
title
'VVS (Feat. JUSTHIS) (Prod. GroovyRoom)'

이번엔 가수를 찾아보자. 가수는 div와 a 태그에 포함되어 있다.

singer = song.select('div.ellipsis.rank02 > a')
len(singer)
4
singer = song.select('div.ellipsis.rank02 > a')[0].text
singer
'미란이 (Mirani)'

책이랑 다르게 쇼미의 힘인지 가수가 여러명인 노래가 1위이다.. 책의 코드들을 수정해야할 것으로 보인다.

# 가수가 여러명인 경우 가수 이름을 저장하는 방법
len_singer = len(song.select('div.ellipsis.rank02 > a'))
singer = ""
for i in range(len_singer):
    singer += song.select('div.ellipsis.rank02 > span > a')[i].text + ", "
singer
'미란이 (Mirani), 먼치맨, Khundi Panda, 머쉬베놈 (MUSHVENOM), '

책의 1위부터 100위까지 가수와 노래 제목을 구하는 for문

for song in songs:
    title = song.select('div.ellipsis.rank01 > span > a')[0].text
    singer = song.select('div.ellipsis.rank02 > span > a')[0].text
    print(title, singer, sep= '|')
for song in songs:
    title = song.select('div.ellipsis.rank01 > span > a')[0].text
    singer = ""
    len_singer = len(song.select('div.ellipsis.rank02 > a'))
    for i in range(len_singer):
        singer += song.select('div.ellipsis.rank02 > span > a')[i].text + ", "
    print(title, singer, sep = ' | ')
VVS (Feat. JUSTHIS) (Prod. GroovyRoom) | 미란이 (Mirani), 먼치맨, Khundi Panda, 머쉬베놈 (MUSHVENOM), 
밤하늘의 별을(2020) | 경서, 
Dynamite | 방탄소년단, 
잠이 오질 않네요 | 장범준, 
내일이 오면 (Feat. 기리보이, BIG Naughty (서동현)) | 릴보이 (lIlBOI), 
힘든 건 사랑이 아니다 | 임창정, 
취기를 빌려 (취향저격 그녀 X 산들) | 산들, 
Lovesick Girls | BLACKPINK, 
Life Goes On | 방탄소년단, 
오래된 노래 | 스탠딩 에그, 
CREDIT (Feat. 염따, 기리보이, Zion.T) | 릴보이 (lIlBOI), 
Savage Love (Laxed - Siren Beat) (BTS Remix) | Jawsh 685, Jason Derulo, 방탄소년단, 
내 마음이 움찔했던 순간 (취향저격 그녀 X 규현) | 규현 (KYUHYUN), 
나랑 같이 걸을래 (바른연애 길잡이 X 적재) | 적재, 
어떻게 이별까지 사랑하겠어, 널 사랑하는 거지 | AKMU (악동뮤지션), 
Achoo (Feat. pH-1, HAON) (Prod. GroovyRoom) | 미란이 (Mirani), 
에잇(Prod.&Feat. SUGA of BTS) | 아이유, 
When We Disco (Duet with 선미) | 박진영, 
ON AIR (Feat. 로꼬, 박재범 & GRAY) | 릴보이 (lIlBOI), 
Freak (Prod. Slom) | 릴보이 (lIlBOI), 원슈타인, Chillin Homie, 스카이민혁 (Skyminhyuk), 
혼술하고 싶은 밤 | 벤, 
흔들리는 꽃들 속에서 네 샴푸향이 느껴진거야 | 장범준, 
늦은 밤 너의 집 앞 골목길에서 | 노을, 
어떻게 지내 (Prod. By VAN.C) | 오반 (OVAN), 
How You Like That | BLACKPINK, 
모든 날, 모든 순간 (Every day, Every Moment) | 폴킴, 
딩가딩가 (Dingga) | 마마무 (Mamamoo), 
뿌리 (Feat. JUSTHIS) (Prod. GroovyRoom) | Khundi Panda, 
아로하 | 조정석, 
METEOR | 창모 (CHANGMO), 
Blueming | 아이유, 
Dolphin | 오마이걸 (OH MY GIRL), 
서면역에서 | 순순희, 
DON'T TOUCH ME | 환불원정대, 
사실 나는 (Feat.전건호) | 경서예지, 
악역 (Feat. 이하이 & 사이먼 도미닉) (Prod. 코드 쿤스트) | 스윙스, 
마음을 드려요 | 아이유, 
작은 것들을 위한 시 (Boy With Luv) (Feat. Halsey) | 방탄소년단, 
I CAN’T STOP ME | TWICE (트와이스), 
거짓말이라도 해서 널 보고싶어 | 백지영, 
오늘도 빛나는 너에게 (To You My Light) (Feat.이라온) | 마크툽 (MAKTUB), 
마리아 (Maria) | 화사 (Hwa Sa), 
뻔한남자 | 이승기, 
Memories | Maroon 5, 
시작 | 가호 (Gaho), 
그날에 나는 맘이 편했을까 | 이예준, 
Snowman | Sia, 
사랑은 지날수록 더욱 선명하게 남아 | 전상근, 
우리 왜 헤어져야 해 | 신예영, 
홀로 | 이하이, 
봄날 | 방탄소년단, 
고독하구만 (Feat. 수퍼비) (Prod. GroovyRoom) | 머쉬베놈 (MUSHVENOM), 
눈누난나 (NUNU NANA) | 제시 (Jessi), 
All I Want For Christmas Is You | Mariah Carey, 
가을밤에 든 생각 | 잔나비, 
살짝 설렜어 (Nonstop) | 오마이걸 (OH MY GIRL), 
Santa Tell Me | Ariana Grande, 
Dance Monkey | Tones And I, 
한잔이면 지워질까 | 황인욱, 
Downtown Baby | 블루 (BLOO), 
2002 | Anne-Marie, 
What Do I Call You | 태연 (TAEYEON), 
사랑 못해, 남들 쉽게 다 하는 거 | 먼데이 키즈 (Monday Kiz), 
안녕 | 폴킴, 
너를 만나 | 폴킴, 
소확행 | 임창정, 
미리 메리 크리스마스 (Feat. 천둥 Of MBLAQ) | 아이유, 
Panorama | IZ*ONE (아이즈원), 
나로 바꾸자 (duet with JYP) | 비, 
여백의 미 (Feat. Jessi, JUSTHIS) (Prod. GroovyRoom) | 머쉬베놈 (MUSHVENOM), 
잘할게 | 이승기, 
처음처럼 | 엠씨더맥스 (M.C the MAX), 
행복해 | 송하예, 
사랑하게 될 줄 알았어 | 전미도, 
Love poem | 아이유, 
이제 나만 믿어요 | 임영웅, 
너의 번호를 누르고 (Prod. 영화처럼) | #안녕, 
너도 아는 | 폴킴, 
Don't Start Now | Dua Lipa, 
우린 어쩌다 헤어진 걸까 | 허각, 
별을 담은 시 (Ode To The Stars) | 마크툽 (MAKTUB), 이라온, 
아무노래 | 지코 (ZICO), 
다시 여기 바닷가 | 싹쓰리 (유두래곤, 린다G, 비룡), 
12:45 (Stripped) | Etham, 
Bad Boy | 청하, Christopher, 
적외선 카메라 | 원슈타인, 
놓아줘 (with 태연) | Crush, 
Paris In The Rain | Lauv, 
Maniac | Conan Gray, 
가다 (Feat. 사이먼 도미닉, The Quiett) (Prod. SLO) | 머쉬베놈 (MUSHVENOM), 
원해 (Feat. 팔로알토) (Prod. 코드 쿤스트) | 스윙스, 맥대디 (Mckdaddy), Khakii (카키), 래원 (Layone), 
ON | 방탄소년단, 
Black Mamba | aespa, 
For You (Feat. Crush) | 이하이, 
12월의 어느 겨울… | 윤도 (YoonDo), 
Blue & Grey | 방탄소년단, 
요즘 | 양다일, 
내 방을 여행하는 법 | 방탄소년단, 
크리스마스니까 | 성시경, 박효신, 이석훈, 서인국, VIXX (빅스), 
모든 밤 너에게 (연애혁명 X 민현 (뉴이스트)) | 민현 (뉴이스트), 

직장인을 위한 데이터 분석 실무 파이썬 / 위키북스

profile
데이터 분석 공부용 벨로그

0개의 댓글