整理东西的时候发现,以前写的一个,在qq听音乐时,发现有首好听的,想下载下来但是要钱。就想,既然能听,那就可以找到MP3文件。(如果听都要收费那就没办法了)
思路如下:
1丶首先到排行榜网址上寻找信息:排行榜由js动态加载,并且一次只显示30首。访问js请求的网页,得到js返回值,将得到的js数据处理,得到歌曲名和歌手信息,存入txt 文件,方便下面进行下载。
2丶通过存有音乐信息的txt,拼接音乐搜索网址,访问它,获取到每首音乐的一个id。
3丶每首歌在播放时都会有播放源链接(即我们需要的下载链接),这个链接需要传入一些参数,最重要的是歌曲存放文件名和vkey。然后播放时,它会通过js请求,返回需要的文件名和vkey,这个js请求url就可以用之前获取到的id构造。
源代码如下,为指定歌曲下载,想批量下载请自行修改,原理一样。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#此程序仅供学习交流使用。
import urllib.request
import json
import re
import urllib.parse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
name = input("输入你想听的歌名or歌名+歌手:")
name = urllib.parse.quote(name)
url = "https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w="+name
headers = {
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"
}
def network(url):
request_url = urllib.request.Request(url,headers=headers)
response = urllib.request.urlopen(request_url).read().decode('utf-8')
return response
def download(songmid,music_name):
#json数据
json_url = "https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?g_tk=5381&jsonpCallback=MusicJsonCallback8796342823761736&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&cid=205361747&callback=MusicJsonCallback8796342823761736&uin=0&" \
"songmid="+songmid+"&filename=C400"+songmid+".m4a&guid=4626869183"
html = network(json_url)
#找到json中music的信息
music_json = json.loads(re.findall(r'^\w+\((.*)\)$',html)[0])
filename = music_json['data']['items'][0]['filename']
vkey = music_json['data']['items'][0]['vkey']
#歌曲的下载链接
download_url = "http://dl.stream.qqmusic.qq.com/"+filename+"?vkey="+vkey+"&guid=4626869183&uin=0&fromtag=66"
ret_url = urllib.request.Request(download_url,headers=headers)
music_url = urllib.request.urlopen(ret_url).read()
with open("./"+music_name+".m4a", "wb") as fb:
fb.write(music_url)
def get():
#加载Chromedriver,百度chromedriver.exe,下载与自己chrome版本一致的。
option = webdriver.ChromeOptions()
option.add_argument('headless')
driver = webdriver.Chrome('D:\Python3\chromedriver.exe',chrome_options=option)
#请自行修改加载的路径
driver.get(url)
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "js_song")))
music = driver.find_element_by_class_name('js_song')
href = music.get_attribute('href')
music_name = music.get_attribute('title')
#匹配到歌曲的id
songmid = re.findall(r'https://y.qq.com/n/yqq/song/(\S+).html',href)[0]
download(songmid,music_name)
if __name__ == '__main__':
get()