본문 바로가기

프로젝트 목록/ParseWEB

ParseWEB [1-11] 멜론 차트 TOP 100 파싱

이번 강좌부터는 음악 차트에서 제공하는 TOP 100에 대한 정보를 파싱해오는 내용을 살펴보겠습니다.


해당 강좌에서는 멜론에서 제공하는 TOP 100에 대한 정보를 가져와 보도록 하겠습니다.

사전 정보 수집

멜론의 경우에도 모바일 페이지가 따로 존재하기 때문에 모바일 페이지에서 차트 정보를 파싱해보도록 하겠습니다.

멜론의 모바일 페이지의 경우 아래와 같은 URL을 가지고 있습니다.

https://m.app.melon.com/index.htm


하지만 PC로 해당 사이트에 접속하게 되면 PC 버전인 페이지로 넘어가는 것을 볼 수 있습니다.


그렇기 때문에 여기서는 PC로 접속을 하더라도 모바일에서 접속하는 것처럼 흉내를 내도록 하는 테크닉을 사용해야 합니다.

어떻게 하면 해당 사이트로 접속한 브라우저가 모바일 환경인지 여부를 알 수 있을지 잠시 생각해봅시다.


해답은 이전 시간에 다루었던 User Agent입니다. User Agent의 정보를 통해서 해당 브라우저가 모바일인지 혹은 PC인지를 알아낼 수 있습니다.

즉 User Agent에 해당하는 정보를 모바일 브라우저의 값으로 변경하여 접속한다면 해당 사이트는 모바일로 접속했다고 인식을 하게 됩니다.

크롬 브라우저에서 모바일 브라우저로 User Agent를 수정하는 방법은 아래와 같이 개발자 도구에서 휴대폰과 태블릿 모양이 있는 부분을 누르시면 됩니다.


이렇게 하면 모바일 페이지에 접근하더라도 PC 버전으로 바뀌지 않는 것을 볼 수 있습니다.


그리고 나서 페이지의 위쪽 탭에 위치한 멜론 차트를 누른 다음에 맨 아래로 내리면 다음과 같이 아래 화살표로 되어 있는 부분을 볼 수 있습니다.


그래서 해당 부분을 누르면 아래쪽에 51위부터 100위까지의 데이터가 붙는다는 것을 확인할 수 있습니다.

이 부분을 통해서 해당 버튼을 누르면 XHR 요청을 보내서 받은 응답을 아래쪽에 붙여준다는 사실을 알 수 있습니다.

이전에 했던 방식과 같이 Network 탭에 가서 XHR 요청을 필터링하면 main_chartPaging.htm?startIndex=51&pageSize=50&rowsCnt=50의 형태의 요청을 볼 수 있습니다.


즉 51위부터 50개의 데이터를 가져오기 때문에 요청할 때 해당 정보를 넘겨준다는 것을 알 수 있습니다.

이를 통해 startIndexrowsCnt 부분을 수정하면 1위부터 100위까지의 정보를 가지고 올 수 있습니다.


그래서 이를 토대로 우리가 가져와야 할 데이터의 주소는 아래와 같습니다.

https://m.app.melon.com/cds/main/mobile4web/main_chartPaging.htm?startIndex=1&pageSize=50&rowsCnt=100


해당 주소로 이동한 다음 요소 선택 기능을 이용하여 1위 노래 제목인 '이 노래가 클럽에서 나온다면'을 선택하면 태그는 p이고 class로는 title을 가진다는 것을 알 수 있습니다.


마찬가지고 1위 노래 가수인 '우디 (Woody)'를 선택하면 태그는 span이고 class로는 name을 가진다는 것을 알 수 있습니다.


이 정보를 이용해서 코드를 작성해보도록 합시다.

구현하기

from bs4 import BeautifulSoup
import requests

def get_content():
    url = 'https://m.app.melon.com/cds/main/mobile4web/main_chartPaging.htm'
    mobile_user_agent = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) '\
        'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Mobile Safari/537.36'
    headers = {'User-Agent': mobile_user_agent}
    params = {'startIndex': 1, 'pageSize': 50, 'rowsCnt': 100}
    req = requests.get(url, params=params, headers=headers)
    content = req.content

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

    title_elems = soup.select('p.title')
    singer_elems = soup.select('span.name')

    titles = map(lambda x: x.text.strip(), title_elems)
    singers = map(lambda x: x.text, singer_elems)

    return list(zip(titles, singers))

result = get_content()

for index, item in enumerate(result):
    print('[{:2}위] {} - {}'.format(index + 1, item[0], item[1]))

시연 결과

아래 이미지와 같이 멜론 차트 TOP 100의 내용을 가지고 오는 것을 볼 수 있습니다.


더 생각해보기

아래 내용은 직접 생각해서 구현을 해보시기 바라며 해당 내용에 대한 답안은 따로 제공하지 않습니다.


  1. PC 버전으로 파싱을 하여 해당 곡에 '좋아요'를 누른 사람 수도 같이 출력해봅시다.
  2. 19금 태그가 있는 경우에는 아래와 같이 값이 이상하게 나오는 것을 볼 수 있습니다. 해당 내용을 어떻게 처리해야 곡 제목만 가지고 올 수 있을지 생각해봅시다.