最近在爬取歌曲下载资源时,遇到一个有趣的挑战——歌曲宝网站的下载按钮触发弹窗,而且下载链接的访问需要调用后台接口确认“操作成功”,才能拿到真实的低品质MP3下载地址。为了实现批量自动下载,我结合 Selenium 模拟浏览器操作和 Requests 发送接口请求,写了一个完整的自动化脚本。今天分享下实现思路和关键点。
一、问题描述
该网站的周下载排行榜页面,歌曲列表在一个表格里,每首歌的详情页里有一个“下载歌曲”按钮。点击后弹出弹窗,用户需选择音质,低品质MP3链接是弹窗里的备用链接。
- 直接用 Requests 请求弹窗页面拿不到下载链接
- 弹窗的下载链接只有点击了一个后台接口
/api/ad-handle
后才有效 - 真实的MP3下载链接在弹窗点击后打开新标签页,地址是CDN的mp3资源链接
- 需要批量处理20页,每页10首歌
二、核心难点
弹窗异步加载和点击流程
需要用 Selenium 模拟点击“下载歌曲”按钮,等待弹窗出现,点击“低品质MP3”链接,拿到真实的下载URL。后台接口请求
必须先调用/api/ad-handle
POST 接口,模拟广告播放确认,才能获得真实可用的下载链接。保持请求状态和Cookie一致
使用 Selenium 操作浏览器后,拿到的 Cookie 需要同步给 Requests,用于调用接口和下载 MP3,否则请求会被拒绝。
三、技术方案
- 使用 Requests 来请求排行榜页面,解析出歌曲详情页URL。
- 使用 Selenium(Chromedriver) 模拟浏览器打开歌曲详情页,执行点击操作,弹出音质选择弹窗。
- 从 Selenium 获取 Cookie,传给 Requests,发送广告确认接口请求。
- 弹窗中点击低品质MP3链接,切换标签页拿真实链接。
- 用 Requests 下载 MP3 文件。
四、关键代码解读
1. Cookie 同步
def cookies_from_driver(driver):
cookies = driver.get_cookies()
cookie_dict = {}
for cookie in cookies:
cookie_dict[cookie['name']] = cookie['value']
return cookie_dict
通过 Selenium 拿到浏览器的所有 Cookie,传给 Requests 保持会话一致。
2. 调用后端接口
def send_ad_handle(session, song_url, headers):
api_url = "https://www.gequbao.com/api/ad-handle"
post_headers = headers.copy()
post_headers.update({
'origin': 'https://www.gequbao.com',
'referer': song_url,
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'x-requested-with': 'XMLHttpRequest',
})
data = ""
resp = session.post(api_url, headers=post_headers, data=data)
return resp.status_code == 200 and resp.json().get('code') == 1
这是成功获得下载授权的关键步骤。
3. 弹窗操作与真实链接获取
mp3_btn = wait.until(EC.element_to_be_clickable((By.ID, "btn-download-mp3")))
mp3_btn.click()
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.jconfirm-box")))
time.sleep(2)
low_quality_link = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.jconfirm-box a.default-link")))
low_quality_link.click()
time.sleep(2)
handles = driver.window_handles
if len(handles) > 1:
driver.switch_to.window(handles[-1])
mp3_url = driver.current_url
driver.close()
driver.switch_to.window(handles[0])
else:
mp3_url = low_quality_link.get_attribute("href")
点击弹窗“低品质MP3”链接后,selenium自动切换到新标签页拿真实URL。
4. 批量爬取和下载
主循环里先解析排行榜页面,再逐个下载:
for page in range(1, PAGES + 1):
url = BASE_URL.format(page)
res = requests.get(url, headers=HEADERS)
soup = BeautifulSoup(res.text, 'html.parser')
table_div = soup.find('div', class_='table-responsive')
links = table_div.find_all('a')
for a in links:
href = a.get('href')
song_url = 'https://www.gequbao.com' + href
song_title = a.text.strip()
download_song(driver, session, song_url, song_title, SAVE_DIR)
time.sleep(2)
五、使用说明
- 需要安装 Python 库:
selenium
,requests
,beautifulsoup4
- 需要对应版本的 Chrome 浏览器和 chromedriver
- 修改
PAGES
和SAVE_DIR
变量设置页数和保存目录 - 脚本支持无头模式,调试时建议注释无头参数查看浏览器行为
六、总结
结合 Selenium 和 Requests,可以绕过传统纯爬虫难以处理的复杂页面交互和授权机制,实现真正的自动化批量下载。这个项目充分体现了自动化测试框架和HTTP请求库的协同优势。
如果你也遇到类似带弹窗授权的网页数据抓取,推荐用类似方法:
- Selenium先浏览器交互
- Requests补充接口调用和资源下载
完整代码放到了github:Marblog