Python을 사용하여 Spotify 데이터를 스크랩하는 방법

댓글: 0

Spotify 재생 목록 데이터는 노래, 아티스트 및 기타 트랙 세부 정보에 대한 정보를 수집하는 데 유용할 수 있습니다. Spotify는 API 키 없이는 일부 데이터에 대한 자세한 액세스를 제공하지 않지만, Python용 Playwright를 활용하면 동적 콘텐츠에 액세스하고 Spotify 웹사이트에서 직접 재생 목록 데이터를 추출할 수 있습니다. 이 문서에서는 Spotify 재생 목록에서 트랙 이름, 밴드 이름, 링크, 트랙 길이 등의 정보를 스크랩하기 위해 Playwright를 구현하는 방법을 설명합니다.

요구 사항 및 설치

시작하려면 동적 페이지 콘텐츠와 HTML 구문 분석을 처리하기 위해 Playwright와 lxml을 설치합니다:


pip install playwright
pip install lxml

그런 다음 Playwright 브라우저를 사용하려면 다음 명령을 사용하여 필요한 브라우저 바이너리를 다운로드합니다:


playwright install

이렇게 설정했으니 이제 Spotify를 스크랩할 준비가 되었습니다.

Spotify 스크래핑 프로세스: 단계별 가이드

Spotify의 콘텐츠는 동적으로 로드되므로 요청이나 기타 간단한 HTTP 라이브러리를 사용하면 JavaScript로 렌더링된 모든 정보를 캡처할 수 없습니다. Playwright는 동적 웹사이트를 직접 탐색하는 것처럼 상호작용할 수 있는 브라우저 자동화 라이브러리로, 스크래핑하기 전에 JavaScript가 로드될 때까지 기다릴 수 있습니다.

또한 Playwright는 프록시 구성을 지원하므로 필요한 경우 다른 IP를 사용하여 Spotify의 속도 제한이나 지역 제한을 피할 수 있습니다.

아래에서 스크래핑에 대한 자세한 단계별 가이드를 확인할 수 있으며, 프로세스를 보다 명확하고 시각적으로 이해할 수 있도록 코드 예제가 포함되어 있습니다.

1단계. HTML 콘텐츠 가져오기 함수 설정하기

fetch_html_content 함수는 Playwright 환경을 초기화하고 브라우저를 실행한 다음 Spotify 재생 목록 URL로 이동합니다. 여기서는 브라우저 인터페이스가 계속 표시되도록 headless=False로 설정했으며(디버깅에 유용함), 자동화된 작업의 경우 True로 설정하면 실행 속도가 빨라집니다.

wait_until='networkidle' 옵션은 페이지 콘텐츠를 캡처하기 전에 네트워크 활동이 안정화될 때까지 기다렸다가 모든 요소가 올바르게 로드되도록 합니다.


from playwright.async_api import async_playwright

async def fetch_html_content(playlist_url):
    async with async_playwright() as p:
        # 필요한 경우 프록시 설정으로 브라우저 실행
        browser = await p.chromium.launch(headless=False)
        page = await browser.new_page()

        # URL로 이동합니다.
        await page.goto(playlist_url, wait_until='networkidle')

        # 네트워크 활동이 안정화될 때까지 시간 허용
        await page.wait_for_timeout(3000)

        # 페이지 콘텐츠 캡처
        page_content = await page.content()

        # 브라우저를 닫습니다.
        await browser.close()

        return page_content


Playwright에서 IP 주소 인증과 함께 프록시를 사용하려면 다음과 같이 실행 기능을 구성합니다:


browser = await p.chromium.launch(headless=True, proxy={"server": "http://your-proxy-server:port"})

이렇게 하면 지정된 프록시 서버를 통해 요청이 라우팅되어 원래 IP를 마스킹하고 잠재적인 스크래핑 제한을 피할 수 있습니다.

2단계. HTML 콘텐츠 구문 분석

lxml의 fromstring 함수를 사용하여 가져온 HTML 콘텐츠에 대한 파서를 생성합니다. 이를 통해 XPath 표현식을 사용하여 특정 데이터를 찾아 추출할 수 있습니다.


from lxml.html import fromstring

page_content = await fetch_html_content('https link')
parser = fromstring(page_content)

3단계. 트랙 정보 추출

XPath 선택기를 사용하면 재생 목록의 각 트랙에 대해 다음과 같은 세부 정보를 수집합니다:

  1. 트랙 이름;
  2. 트랙 URL;
  3. 아티스트 이름;
  4. 아티스트 URL;
  5. 트랙 지속 시간.

track_names = parser.xpath('//div[@data-testid="tracklist-row"]//a[@data-testid="internal-track-link"]/div/text()')
track_urls = parser.xpath('//div[@data-testid="tracklist-row"]//a[@data-testid="internal-track-link"]/@href')
track_urls_with_domain = [f"https://open.spotify.com/{url}" for url in track_urls]
artist_names = parser.xpath('//div[@data-testid="tracklist-row"]//div[@data-encore-id="text"]/a/text()')
artist_urls = parser.xpath('//div[@data-testid="tracklist-row"]//div[@data-encore-id="text"]/a/@href')
artist_urls_with_domain = [f"https://open.spotify.com/{url}" for url in artist_urls]
track_durations = parser.xpath('//div[@data-testid="tracklist-row"]//div[@class="PAqIqZXvse_3h6sDVxU0"]/div/text()')

URL 목록은 Spotify 도메인으로 완성되어 정규화된 링크를 생성합니다.

4단계. 데이터를 CSV 파일로 저장

데이터를 수집한 후에는 이를 CSV 파일에 기록합니다. 파일의 각 행에는 트랙 이름, 트랙 URL, 아티스트 이름, 아티스트 URL, 트랙 지속 시간이 포함됩니다.


import csv

rows = zip(track_names, track_urls_with_domain, artist_names, artist_urls_with_domain, track_durations)
csv_filename = "spotify_playlist.csv"

with open(csv_filename, mode='w', newline='') as file:
    writer = csv.writer(file)
    # 헤더 쓰기
    writer.writerow(["track_names", "track_urls", "artist_names", "artist_urls", "track_durations"])
    # 행 쓰기
    writer.writerows(rows)

print(f"Data successfully written to {csv_filename}")

이렇게 하면 분석하기 쉽고 추가 애플리케이션에서 사용하기 쉬운 잘 구조화된 CSV 파일이 생성됩니다.

프록시를 지원하는 전체 코드 예제

다음은 간소화된 Spotify 스크래핑 프로세스를 위한 모든 단계를 결합한 전체 코드입니다:


from playwright.async_api import async_playwright
from lxml.html import fromstring
import csv

async def fetch_html_content(playlist_url):
    async with async_playwright() as p:
        # 필요한 경우 프록시 옵션을 사용하여 브라우저 실행
        browser = await p.chromium.launch(headless=False, proxy={"server": "http://your-proxy-server:port", "username": "username", "password": "password"})
        page = await browser.new_page()

        # URL로 이동합니다.
        await page.goto(playlist_url, wait_until='networkidle')
        
        # 네트워크 활동이 안정될 때까지 기다립니다.
        await page.wait_for_timeout(3000)
        
        # 페이지 콘텐츠 캡처
        page_content = await page.content()

        # 브라우저를 닫습니다.
        await browser.close()
        
        return page_content

page_content = asyncio.run(fetch_html_content('https link'))
parser = fromstring(page_content)


# 세부 정보 추출
track_names = parser.xpath('//div[@data-testid="tracklist-row"]//a[@data-testid="internal-track-link"]/div/text()')
track_urls = parser.xpath('//div[@data-testid="tracklist-row"]//a[@data-testid="internal-track-link"]/@href')
track_urls_with_domain = [f"https://open.spotify.com/{url}" for url in track_urls]
artist_names = parser.xpath('//div[@data-testid="tracklist-row"]//div[@data-encore-id="text"]/a/text()')
artist_urls = parser.xpath('//div[@data-testid="tracklist-row"]//div[@data-encore-id="text"]/a/@href')
artist_urls_with_domain = [f"https://open.spotify.com/{url}" for url in artist_urls]
track_durations = parser.xpath('//div[@data-testid="tracklist-row"]//div[@class="PAqIqZXvse_3h6sDVxU0"]/div/text()')

# CSV에 쓰기
rows = zip(track_names, track_urls_with_domain, artist_names, artist_urls_with_domain, track_durations)
csv_filename = "spotify_playlist.csv"

with open(csv_filename, mode='w', newline='') as file:
    writer = csv.writer(file)
    writer.writerow(["track_names", "track_urls", "artist_names", "artist_urls", "track_durations"])
    writer.writerows(rows)

print(f"Data successfully written to {csv_filename}")

Playwright와 함께 Python을 사용하여 Spotify 재생 목록 데이터를 수집하면 트랙 정보를 추출하고 분석하기 위해 동적 콘텐츠에 액세스할 수 있습니다. 프록시로 Playwright를 구성하면 속도 제한을 처리하여 재생 목록 데이터를 수집하는 안정적인 방법을 만들 수 있습니다. 이 설정은 상세한 분석을 위한 가능성을 열어주며 다른 Spotify 콘텐츠 유형에도 쉽게 적용할 수 있습니다.

댓글:

0 댓글