BeautifulSoup과 Request를 활용하여 웹 스크래핑을 해보도록 하겠습니다.
BeautifulSoup은 웹 사이트의 정보를 쉽게 스크랩할 수 있도록 도와주는 파이썬 라이브러리입니다.
그리고 이를 수행하기 위해 웹 사이트에 https 요청을 보낼 수 있도록 도와주는 라이브러리인 Requests도 활용하도록 하겠습니다.
작업 환경은 visual studio code 편집기와 Chrome 웹 브라우저를 사용했습니다.
크롬 웹사이트에서 F12를 누르시면 이렇게 개발자 도구가 나타나게 됩니다.
앞으로 이를 활용해서 우리가 필요로 하는 데이터를 뽑아내도록 하겠습니다.
(작성일 11월 8일 00시 기준으로 나타난 멜론차트 내용입니다.)

BeautifulSoup, Requests 설치
pip install beautifulsoup4
pip install requests
다운로드한 라이브러리를 import 해줍니다.
import requests
from bs4 import BeautifulSoup
웹 사이트에 https요청하여 일단 멜론 차트 페이지의 모든 텍스트 내용을 가져와보도록 하겠습니다.

pg=requests.get("https://www.melon.com/chart/index.htm") #웹페이지 https요청
sp=BeautifulSoup(pg.text,"html.parser") #요청받은 페이지의 내용을 BeautifulSoup객체로 전달
print(sp.text)
그런데,

아무런 내용이 표시되지 않았습니다...
그래서 구글링을 해보니, 특정 웹사이트의 서버에서 크롤러를 봇의 부적절한 접근으로 인식할 수 있다고 합니다. (네이버 메인 사이트로 실험해 본 결과 네이버 웹사이트는 위의 코드가 작동했습니다.) 즉, 무분별한 크롤링을 통해 서버에 과부하가 오는 것을 방지하기 위한 대비책이라고 할 수 있습니다. 이를 해결하기 위해서는 Header에 크롤러를 사용하는 것이 봇이 아니라 사람이다!!라는 정보(User-Agent)를 기입하여 웹사이트에 요청하는 방법을 활용할 수 있습니다. 코드를 수정해보도록 하겠습니다.
먼저 아래의 페이지에서 User Agent String explained : 아래의 내용을 복사해줍니다.(Mozilla/5.0까지만 기입해도 정상적으로 작동했습니다.)
http://www.useragentstring.com/
UserAgentString.com - unknown version
www.useragentstring.com
import urllib.request
import urllib.parse
from bs4 import BeautifulSoup
url='https://www.melon.com/chart/index.htm'
header={'User-Agent':'Mozilla/5.0'}
mod=urllib.request.Request(url,headers=header)
htmlcontent=urllib.request.urlopen(mod).read()
#헤더에 사이트에 보낼 User-Agent의 내용을 담아 요청함
bs=BeautifulSoup(htmlcontent,'html.parser')
print(bs.text)

이제 정상적으로 작동했습니다!! 지금의 출력 결과는 멜론 차트 페이지의 모든
html 소스에서 text 부분을 파싱해온 결과를 출력한 것입니다.
여기서 우리는 필요한 멜론차트의 노래 정보만 골라내면 완성입니다. 아까 다시 메인 페이지에서 우리가 필요한 정보가 어디에 있는지부터 찾아보도록 하겠습니다. 일단 멜론 차트 1위의 곡 정보가 어디에 위치하는지 알아보겠습니다. 아래 그림과 같이 F12를 누르시고 개발자 도구의 좌상단의 Elements 카테고리를 선택하시고 빨간색 네모 박스의 아이콘을 클릭합니다.

아래 그림과 같이 1위 노래의 제목에 마우스를 갖다대면 현재 마우스 커서가 위치한 내용이 html 코드의 어디에 위치하는지 알 수 있습니다. 여기서 우리는 필요한 태그를 골라냅니다.

조금 자세히 보도록 하겠습니다.

우리가 필요한 "쉬어 (Feat. MINO) (Prod. GRAY)" 라는 정보는
<div class="ellipsis rank01"> 아래의 <span> 아래의 a태그 안의 text로 위치해 있습니다.
아래의 코드를 이용해 div 태그부터 접근해 보도록 하겠습니다.
title=bs.find_all('div','ellipsis rank01')
위의 코드를 보도록 하겠습니다.
div라는 태그를 검색할건데 클래스가 ellipsis와 rank01을 포함하는 div태그를 모조리 검색하는 것입니다.
우리가 필요한 데이터는 그 아래의 하위 태그인 a태그의 text입니다. 일단 뭐든 출력이 되는지 확인해 봤습니다.
print(title.text)

그런데 또 안 됐습니다.... ㅋㅋㅋㅋㅋ
그래서 먼저 title이라는 녀석이 어떤 데이터 타입인지 알아봤습니다.
print(type(title))
>>> <class 'bs4.element.ResultSet'>
bs4.element.ResultSet이라는 데이터 타입인데 뭔가 그냥 데이터셋이라는 느낌을 받아 리스트가 아닐까? 해서 리스트 원소 호출을 해봤습니다.
print(type(title[0]))
>>> <class 'bs4.element.Tag'>
이번엔 bs4.element.Tag라는 데이터 타입입니다. 여기서 뭔가를 찾을 수 있을 것 같아 bs4 공식 문서를 찾아봤습니다.
Beautiful Soup Documentation — Beautiful Soup 4.9.0 documentation
Non-pretty printing If you just want a string, with no fancy formatting, you can call str() on a BeautifulSoup object (unicode() in Python 2), or on a Tag within it: str(soup) # ' I linked to example.com ' str(soup.a) # ' I linked to example.com ' The str(
www.crummy.com
문서에서 Ctrl + F로 element.tag를 검색하니 딱 한 구간 나오더군요. 그 이후부터 찾아보니 해당 클래스의 사용법이 나와있었습니다.
내용을 출력해보도록 하겠습니다.
print(title[0])
>>>
<div class="ellipsis rank01"><span>
<a href="javascript:melon.play.playSong('1000002721',34215822);" title="쉬어 (Feat. MINO) (Prod. GRAY) 재생">쉬어 (Feat. MINO) (Prod. GRAY)</a>
</span></div>
잘 나오네요! 이제 여기서 필요한 div 태그아래의 a태그의 text만 출력하면 1위의 곡 제목이 나오게 됩니다.
print(title[0].a.text)
>>>쉬어 (Feat. MINO) (Prod. GRAY)

이제 거의 다 끝났습니다. 1위부터 10위까지만 출력해보도록 하겠습니다!

for i in range(10):
print(title[i].a.text)

잘 되네요!!