抓取 spotify 网页界面

Scrape spotify web interface

我正在尝试使用 python 和 splinter 获取 Spotify 上许多艺术家的热门歌曲的播放次数。

如果您在下面填写用户名和密码,您应该可以运行验证码。

from splinter import Browser
import time
from bs4 import BeautifulSoup

browser = Browser()
url = 'http://play.spotify.com'
browser.visit(url)
time.sleep(2)
button = browser.find_by_id('has-account')
button.click()
time.sleep(1)
browser.fill('username', 'your_username')
browser.fill('password', 'your_password')
buttons = browser.find_by_css('button')
visible_buttons = [button for button in buttons if button.visible]
login_button = visible_buttons[-1]
login_button.click()
time.sleep(1)
browser.visit('https://play.spotify.com/artist/5YGY8feqx7naU7z4HrwZM6')
time.sleep(10)

到目前为止,还不错。如果你打开 firefox,你会看到 Miley Cyrus 的艺术家页面,包括热门曲目的播放次数。

如果打开 Firefox Developer Tools Inspector 并将鼠标悬停,您可以在 .tl-highlight 元素中看到歌曲的名称,在 .tl-listen-count 元素中看到播放次数。但是,我发现不可能(至少在我的机器上)使用 splinter 访问这些元素。此外,当我尝试获取整个页面的源代码时,我在 Firefox 中通过将鼠标悬停在它们上面可以看到的元素不会显示在表面上的页面源代码中。

html = browser.html
soup = BeautifulSoup(html)
output = soup.prettify()
with open('miley_cyrus_artist_page.html', 'w') as output_f:
    output_f.write(output)
browser.quit()

我认为我对 Web 编程的了解还不足以了解这里的问题——Firefox 清楚地看到所有 DOM 元素,但驱动 Firefox 的碎片却看不到。

关键问题是 iframe 包含带有曲目列表的艺术家页面。在搜索元素之前,您需要切换到它的上下文

frame = browser.driver.find_element_by_css_selector("iframe[id^=browse-app-spotify]")
browser.driver.switch_to.frame(frame)

非常感谢@alecxe,以下代码可以提取艺术家的信息。

from splinter import Browser
import time
from bs4 import BeautifulSoup
import codecs

browser = Browser()
url = 'http://play.spotify.com'
browser.visit(url)
time.sleep(2)
button = browser.find_by_id('has-account')
button.click()
time.sleep(1)
browser.fill('username', 'your_username')
browser.fill('password', 'your_password')
buttons = browser.find_by_css('button')
visible_buttons = [button for button in buttons if button.visible]
login_button = visible_buttons[-1]
login_button.click()
time.sleep(1)
browser.visit('https://play.spotify.com/artist/5YGY8feqx7naU7z4HrwZM6')
time.sleep(30)

CORRECT_FRAME_INDEX = 6
with browser.get_iframe(CORRECT_FRAME_INDEX) as iframe:
    html = iframe.html
    soup = BeautifulSoup(html)
    output = soup.prettify()
    with codecs.open('test.html', 'w', 'utf-8') as output_f:
        output_f.write(output)
browser.quit()