스파르타 웹개발 종합반 3주차 - 과제

지니뮤직 스크래핑

순위/곡제목/가수를 스크래핑하여 출력하는 코딩을 작성하자.

  • 지니뮤직 사이트에 들어가서 해당 요소가 어느 셀렉터에 위치해 있는지를 파악한다.
# rank = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.number')
# artist = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.artist.ellipsis')
# title = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis')
  • 해당 셀렉터의 경로보다 상위 위치에서 전부 선택하는 셀렉터 하나를 정의한 뒤 반복문을 수행하여 하위 셀렉터의 결과를 반복적으로 출력한다.
songs = soup.select('#body-content > div.newest-list > div > table > tbody > tr') 
#tr 까지는 내가 가져오려는 정보의 경로가 
#일치하므로 이렇게 선언을 해놓고 사용하면 편리하다.
import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient
import certifi
ca = certifi.where()

client = MongoClient('mongodb+srv://test:[email protected]/Cluster0?retryWrites=true&w=majority', tlsCAFile=ca )
db = client.dbsparta

#유저가 부른 것처럼 하기 위한 header 속성
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20210701',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')

# rank = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.number')
# artist = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.artist.ellipsis')
# title = soup.select_one('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis')

songs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for song in songs:
    ranks = song.select_one('td.number')
    artists = song.select_one('td.info > a.artist.ellipsis')
    titles = song.select_one('td.info > a.title.ellipsis')

    if ranks is not None:
        rank = ranks.text[0:2].strip()
        title = titles.text.strip()
        artist = artists.text

        print(rank,title,artist)

title = song.select_one('td.info > a.title.ellipsis').text.strip()

이렇게 해서 실행을 하면 결과가 잘 나오는듯 하지만 한가지 문제점이 있다.

중간에 이렇게 거대한 공백이 생겨버리는데, 지니 뮤직 사이트로 들어가 해당 항목을 조사해 봤더니,

해당 항목의 제목에 19금이라는 마크가 붙어있었고, 이를 출력하는 과정에서 공백이 발생한 것이었다.

  • 19금이라는 항목이 생길 경우 해당 공백을 제거할 수 있게 코드를 수정하는 과정에서 strip()을 자세히 공부하게 되었다.

Python의 String은 다음 함수를 제공합니다.
strip([chars]) : 인자로 전달된 문자를 String의 왼쪽과 오른쪽에서 제거합니다.
lstrip([chars]) : 인자로 전달된 문자를 String의 왼쪽에서 제거합니다.
rstrip([chars]) : 인자로 전달된 문자를 String의 오른쪽에서 제거합니다.

이 정보를 참고하고 연습을 해봤는데, 위 정보의 결과라면 출력하는 값은 분명 Water가 제거된 값이라고 예상 했지만,

text = ' Water boils at 100 degrees'

tests = text.strip('Water')

print(tests)


지워지지 않는다.

그런데 Water 의 좌측에 있는 공백을 제거한뒤에 실행해보니

Water가 지워졌다.

※ stirip([chars])는 해당 문자열 바깥쪽에 공백이 없어야 제대로 작동을 한다.

그럼 다시 과제로 돌아와서, 이미 출력하고자 하는 title값에 strip()을 적용했기 때문에 바깥쪽의 공백은 없다. 따라서 '19금을 lstrip("19금")을 사용해서 제거한뒤 따로 19금이라는 문구를 추가해서 strip()으로 공백을 제거해보자' 라고 생각을 했다.

for song in songs:
    ranks = song.select_one('td.number')
    artists = song.select_one('td.info > a.artist.ellipsis')
    titles = song.select_one('td.info > a.title.ellipsis')

    if ranks is not None:
        rank = ranks.text[0:2].strip()
        title = titles.text.strip()
        if '19금' in title:
            title = "19금" + title.lstrip('19금').strip() 
            # 19금 단어를 제거하고, 19금 단어를 추가한뒤 공백제거
        artist = artists.text

        print(rank,title,artist)

제대로 작동했다.

과제를 수행하는 도중에 변수가 발생했지만 해결 방안을 찾아서 해결해 나가는 보람이 있었다. 사용자가 보는 페이지를 구현하고, 이젠 서버와 db, 그리고 웹 스크래핑으로 데이터를 얻어오는 것까지 배웠다. 이 둘을 모두 사용해서 웹 서비스를 수월하게 구축할 수 있는 실력이 될 때 까지 열심히 공부해야겠다고 생각한다.

좋은 웹페이지 즐겨찾기