오늘 오전에 배운 멜론차트 크롤링을 이용해서 DB에 넣어보자.

tinyint unsigned를 사용함TINYINT (signed) : -128 ~ 127TINYINT UNSIGNED : 0 ~ 225# 날짜, 순위, 가수, 제목, songid 를 집어넣는 테이블 만들기
# -> 아이디어! 이걸 이용해서 노래방 번호도 크롤링해서 매칭시켜보는 걸 해보자.
# 혹은 날짜별 순위 변동을 추정하거나?
import MySQLdb
conn = MySQLdb.connect(host='myserver', user='play', passwd='123', db='encore') #autocommit=True
cursor = conn.cursor()
song_tbl_create = """CREATE TABLE songs(
song_id INT PRIMARY KEY,
singer VARCHAR(100) NOT NULL,
title VARCHAR(150) NOT NULL,
album VARCHAR(150) NOT NULL,
released DATE NOT NULL,
genre VARCHAR(50) NOT NULL,
lyrics TEXT NULL);"""
top100_tbl_create = """CREATE TABLE top100(
chart_date DATE NOT NULL,
ranking TINYINT UNSIGNED NOT NULL,
song_id INT NOT NULL,
UNIQUE KEY (chart_date, ranking));"""
# cursor.execute(song_tbl_create)
cursor.execute(top100_tbl_create)
conn.commit()
from bs4 import BeautifulSoup
import re
import pandas as pd
from datetime import datetime
p = re.compile("[0-9]+")
bs = BeautifulSoup(r.text)
# 100위까지 +로 합치기 가능. bs4 내부에 __add__가 구현되어 있음.
data = bs.find("div", class_='service_list_song type02 d_song_list').find_all('tr', class_='lst50') + bs.find("div", class_='service_list_song type02 d_song_list').find_all('tr', class_='lst100')
songs_data = []
chart_date_ = datetime.today().strftime("%Y-%m-%d").format()
for i, x in enumerate(data):
tmp = x.find_all('a')
song_id_ = p.findall(x.find(class_="btn button_icons type03 song_info")['href'])[0]
ranking_ = i+1
title_ = x.find(class_='ellipsis rank01').find('a').text
singer_ = ', '.join(list(set([y.text for y in x.find("div", class_='ellipsis rank02').find_all('a')])))
url_ = "<https://www.melon.com/song/detail.htm?songId={}>".format(song_id_)
songs_data.append({
'song_id' : song_id_,
'title' : title_,
'singer' : singer_,
'url' : url_
})
# print(f"{i+1}위 - {title_} - {singer_} - {song_id_} \n {url_}")
# top100 테이블 먼저 채우기
top100_data = [chart_date_, ranking_, song_id_]
cursor.execute("INSERT INTO top100 VALUES (%s, %s, %s)", top100_data)
conn.commit()
for s in songs_data:
url_ = s['url']
lyrics_repose = requests.get(url_, headers= head)
lyrics_bs = BeautifulSoup(lyrics_repose.text)
# 가사 추출
s['lyrics'] = BeautifulSoup(str(lyrics_bs.find('div', id='d_video_summary')).replace("<br/>", '\n')).text.strip()
# 세부정보 추출
detail = lyrics_bs.find('div', class_='meta').find_all('dd')
s['album'] = detail[0].text # 앨범
s['released'] = detail[1].text # 발매일
s['genre'] = detail[2].text # 장르
songs_data # 40.2초 걸림-> url에 계속 요청하는 거라 시간을 줄일 방법이 있을까?
songs_rows = [(s['song_id'], s['singer'], s['title'], s['album'], s['released'], s['genre'], s['lyrics']) for s in songs_data]
# 처음에 딕셔너리 구조 자체를 순서대로 할 걸!
cursor.executemany("""INSERT INTO songs (song_id, singer, title, album, released, genre, lyrics)
VALUES (%s, %s, %s, %s, %s, %s, %s)""", songs_rows)
conn.commit()

잘 들어갔다!
