2023.06.27 Python 크롤링(2)

2023. 6. 28. 00:23Lang/Python

지금까지 공부한 걸로 멜론차트를 크롤링 해보았다.

 

 

1. 멜론차트 TOP100 접속

import requests as req 
from bs4 import BeautifulSoup as bs 
res=req.get('https://www.melon.com/chart/index.htm')
res

멜론 사이트에 접근한 결과값

응답으로 Response [406]이 떴다.

400번대가 뜨면 '클라이언트(요청) 부분에서 오류가 발생했을 때'라고 했는데

이 경우는 사이트 자체적으로 Python으로 접속을 못하게 막아둔거라한다.

 

이런 상황에는 우회접속을 하면 된다

 

 -> 우회접속 방법 :

1) 개발자모드(f12) 에서 NETWORK 클릭
2) F5버튼으로 새로고침
3) 스크롤 맨 위로 올려서 document 타입의 html 문서 접근
4) Headers 속성 맨 아래에 User-Agent 값 복사
5) 파이썬 코드에서 딕셔너리 형태로 넣어서 get 메소드의 headers 값에 대입

 

코드로 정의하면,

h= {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'}

res=req.get('https://www.melon.com/chart/index.htm', headers = h)
res

우회접속해서 멜론사이트에 접근한 결과값

Response [200]이 나와 성공적으로 요청,응답을 받았다.

 

 

2. 노래 제목 데이터 수집

res.text
soup = bs(res.text, 'lxml')
song=soup.select('div ellipsis.rank01>span>a')
song

노래 제목 수집 결과 값

페이지의 텍스를 긁어와서 bs 객체화를 했다. 

이후 개발자모드로 데이터가 들어 있는 태그를 가져왔는데

빈 리스트가 출력된다.

 

이유는 div 와 elipsis 사이에 공백이 있기 때문이다.

이러한 공백은 .(온점)으로 채워야한다.

(참고로 div와 elipsis는 모두 rank01이라는 클래스명을 가진 클래스이고 각자 span과 그의 자식인 a태그를 자식 선택자로 가지고 있는 구조이다.)

 

song=soup.select('div.ellipsis.rank01>span>a')
len(song)

song리스트의 길이 확인

TOP100페이지 이기때문에 제대로 데이터가 들어왔는 지 len()함수로 확인해 봤다

결과로 100이 나왔으므로 원하는 노래제목 리스트의 생성을 성공했다.

 

 

3. 가수 데이터 수집

노래제목 바로 아래 있는 태그를 선택한 결과

ㄴ> 빈 리스트가 나오고 실패했다.

그 옆에 자식선택자(>)로 a 태그를 추가 했더니 len() 함수 값이 105가 나왔다

찾아보니 듀엣 같이 한곡을 두명이상의 가수가 부른 경우가 존재했다.

이대로 리스트에 담으면 노래제목과 가수가 1대1 매칭이 되지 않으므로 다시 시도했다

 

singer=soup.select('span.checkEllipsis')
len(singer)

다른 태그를 활용해 데이터를 선택한 결과

100개의 값이 담기고

2명의 가수가 부른 노래 순위를 출력해봤다.

singer[70].text

 

두 가수가 하나의 리스트 인덱스에 들어가 있다(근데 정국이 방탄소년단 아닌가? 왜 따로 이름을 썼지??)

ㄴ> 각각 1개의 인덱스를 차지 하던 값이 하나의 인덱스 속으로 들어갔다는 것을 확인했다.

 

 

4. 노래 제목과 가수 리스트를 생성

songlist=[] # 1번
for i in range (0,99) : #2번
    songlist.append(song[i].text) #3번

singerlist=[]
for i in singer :
    singerlist.append(i.text)

제목, 가수 모두 빈리스트를 만든 뒤 반복문을 활용해서 값을 채워 넣었다

-> list에 값을 넣을 때는 .append() 함수를 써야한다.

 

 

5. 크롤링한 데이터를 DataFrame 형식으로 만들기

songlist=[]
singerlist=[]
ranklist = []

for i in range(len(song)):
    songlist.append(song[i].text)
    singerlist.append(singer[i].text)
    ranklist.append(i+1)

dic = { '노래 제목' : songlist, '가수명' : singerlist, '순위': ranklist}

import pandas as pd
melon=pd.DataFrame(dic)

melon.set_index('순위', inplace = True)
melon

pandas라이브러리의 DataFrame으로 만든 크롤링 데이터의 표

-> .set_index('인덱스의 컬럼명', inplace= True / False) :

       - inplace는 함수를 실행했을 때 변수에 값을 대체해서 저장할지(True) 아니면 보이고 말지(False) 정한다.

       ( Python 에서는 True/False 앞을 대문자로 쓴다는 거 주의하자)

 

 

6. 데이터 프레임을 csv파일로 만들기

melon.to_csv('멜론차트.txt', encoding = "EUC-KR")

ㄴ> 위 코드로 작성하면 melon에 들어가 있는 DataFrame이 외부에 csv파일로 생성된다.

ㄴ> 한국어가 들어갔을 경우 encoding은 필수다. (안 그러면 글자가 깨져서 알아볼 수 없다)