使用Python抓取Web端QQ音乐排行榜 批量下载QQ音乐到本地

鳄鱼君

发表文章数:642

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Python » 使用Python抓取Web端QQ音乐排行榜 批量下载QQ音乐到本地

这次抓取的为QQ音乐排行榜,我们通过浏览器抓包,直接找m4a文件,这个是音乐文件:

使用Python抓取Web端QQ音乐排行榜 批量下载QQ音乐到本地

QQ音乐这个url下载地址需要一个参数vkey,然后还需要构造URL,观察URL发现,基本每个url都是以http://isure.stream.qqmusic.qq.com/C400开头,后面的值可以在这个页面找到:

使用Python抓取Web端QQ音乐排行榜 批量下载QQ音乐到本地

那么现在就剩vkey这个参数了。通过浏览器不断的刷新请求观察发现,vkey参数存在于js文件中,我们可以使用json格式工具查看一下,是否有我们寻找的vkey。

json格式工具推荐:http://www.bejson.com

这里略过寻找的步骤,在以:https://u.y.qq.com/cgi-bin/musicu.fcg?callback,这个url开头的plain文件中找到了vkey的存在,那么现在就是如何构造这个url请求,还需要知道这个url的参数,观察参数变化的有data和jsonpCallback,callback是变化的,data里面变化的就是songmid,就是我们前面找出来C400后面的参数。参考代码:

import requests,json,re,os
from lxml import etree
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
from selenium.common.exceptions import TimeoutException
class QQMusic():
    def __init__(self):
        self.headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
}
        self.url='https://y.qq.com/n/yqq/toplist/4.html'
    def down_music(self,c4,music_name):
        """
        参数不是固定的,可根据自身情况粘贴浏览器中的参数音乐播放页面:https://u.y.qq.com/cgi-bin/musicu.fcg?
        songmid最重要
        :param c4:
        :param music_name:
        :return:
        """
        self.data=json.dumps({"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"2891348329","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"2891348329","songmid":[c4],"songtype":[0],"uin":"1552797557","loginflag":1,"platform":"20"}},"comm":{"uin":1552797557,"format":"json","ct":24,"cv":0}})
        self.params={
            "callback":"getplaysongvkey6354954596402418",
            "g_tk":"1368429410",
            "jsonpCallback":"getplaysongvkey6354954596402418",
            "loginUin":"1552797557",
            "hostUin":"0",
            "format":"jsonp",
            "inCharset":"utf8",
            "outCharset":"utf-8",
            "notice":"0",
            "platform":"yqq",
            "needNewCode":"0",
            "data":self.data
        }
        url = 'https://u.y.qq.com/cgi-bin/musicu.fcg?'
        try:
            html = requests.get(url,headers=self.headers,params=self.params)
            # html.text开始的参数我们需要提取出来,不然会报错,转不了json字典格式的
            s = re.compile('.*?\((.*?)\)', re.S)
            data = re.findall(s, html.text)[0]
            music = json.loads(data)
            purl = music['req_0']['data']['midurlinfo'][0]['purl']
            down_url = f'http://111.6.166.23/amobile.music.tc.qq.com/{purl}'
            # print(down_url)
            self.download(down_url,music_name)
        except Exception as e:
            return None
    def download(self,down_url,music_name):
        print('正在下载歌曲:%s' % music_name)
        file_path = '{0}/{1}.{2}'.format(os.getcwd(), music_name, 'm4a')

        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(requests.get(down_url).content)

    def get_music(self):
        """
        提取所有的排行榜页面
        :return:  排行榜url
        """
        try:
          html=requests.get(self.url,self.headers).content
          tree=etree.HTML(html)
          for i in tree.xpath('//dd[@class="toplist_nav__item"]'):
            href='https:'+i.xpath('./a/@href')[0]
            yield href
        except Exception as e:
          return None
    def get_detail(self,url):
        """
        由于排行榜页面的数据没有在源代码中,所以使用selenium获取
        :param url:
        :return:
        """
        # option = webdriver.ChromeOptions()
        # option.add_argument('headless')
        # driver = webdriver.Chrome(options=option)
        try:
            option = webdriver.FirefoxOptions()  # 设置首选项,无头浏览器,就是看不到浏览器的操作,后台进行
            option.add_argument('-headless')  #火狐无头模式
            driver =webdriver.Firefox(options=option)  #这里使用火狐浏览器
            driver.get(url)
          # 等待所有的class="songlist__songname_txt"都加载出来,这个是歌曲的名字
            WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "songlist__songname_txt")))
            # 然后我们提取这个歌曲的相关属性,C400
            lis = driver.find_elements_by_class_name('songlist__songname_txt')
            #href="https://y.qq.com/n/yqq/song/000OjsEW0QrPAd.html"
            pattern = re.compile(r'https://y.qq.com/n/yqq/song/(.*?).html')  #通过正则提取C400后面的值
            for i in range(lis.__len__()):
              li = lis.__getitem__(i)
              # 找到class="js_song",这个才是我们需要的
              a = li.find_element_by_class_name('js_song')
              href = a.get_attribute('href')
              music_name = a.get_attribute('title')
              c4 = re.match(pattern, href).group(1)
              yield c4,music_name
        except TimeoutException as e:
            return None
    def start(self):
        for url in self.get_music():
            for k,v in self.get_detail(url):

                self.down_music(k, v)


if __name__=='__main__':
  qq=QQMusic()
  qq.start()

音乐保存在当前目录下,可以自行修改,参数也不是固定的可能随时都会失效,同样参数的位置我们已经找到了,就没什么难度了。使用的是selenium抓取排行榜的歌曲信息,比较慢,可以借鉴修改一下。

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《使用Python抓取Web端QQ音乐排行榜 批量下载QQ音乐到本地》 发布于2020-02-24

分享到:
赞(3) 赏杯咖啡

评论 抢沙发

7 + 2 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册