喜馬拉雅
網頁分析
- 打開我們要爬取的音樂專輯https://www.ximalaya.com/ertong/424529/ - F12打開開發者工具 - 點擊XHR 隨便點擊一首歌曲會看到存儲所有歌曲的地址【json格式】 - 正常情況下我們直接用requests請求上面的地址就可以直接獲取歌曲的所有信息
- 我們拿着上面獲取的地址向瀏覽器發起請求,發現沒有返回任何信息 - 我們查看請求頭中的信息發現有一個xm-sign參數,值為加密后的字符串,就是這個參數使我們獲取不到數據 - 31a0dbb5916dfe85d62d8fa5988efc43(36)1563537528652(26)1563537531252 - 后面的時間戳為服務器時間戳和系統當前時間戳,計算過期時間 - 我們分析出xm-sign參數的加密規則,每次請求都在headers加上我們自己生成的xm-sign參數即可
加密方式: ximalaya-時間戳(sha1加密) + (100以內隨機生成一個數) + 服務器時間 + (100以內隨機生成一個數) + 系統當前時間 校驗方式: ximalaya-時間戳(sha1加密) + 服務器時間
獲取地址
請求地址
告訴我們沒有標志,此時感覺我們在請求時少了點參數,去查看請求頭
查看請求頭
后端邏輯代碼
- 下載安裝node.js https://nodejs.org/en/download/ 安裝方式:https://blog.csdn.net/cai454692590/article/details/86093297 - 獲取服務器時間戳 - 調用js代碼中的函數生成xm-sign參數 - 在headrs中加上生成的xm-sign參數像瀏覽器發起請求 - 獲取數據進行持久化
js代碼需要改的
目標地址:
加密方式:
代碼實現
安裝pyexecjs模塊
pip install pyexecjs

# -*- coding: utf-8 -*- # @Time : 2019/7/19 19:05 import requests import os import re from bs4 import BeautifulSoup import lxml import json import execjs # 操作js代碼的庫 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36', 'Accept': 'text/html,application/xhtml+ xml,application/xml;q = 0.9,image/webp,image/apng,*/*;q=0.8, application/signe-exchange;v = b3', 'Host': 'www.ximalaya.com' } '''爬取喜馬拉雅服務器系統時間戳,用於生成xm-sign''' def getxmtime(): url="https://www.ximalaya.com/revision/time" response = requests.get(url, headers=headers) html = response.text return html '''利用xmSign.js生成xm-sign''' def exec_js(): #獲取喜馬拉雅系統時間戳 time = getxmtime() #讀取同一路徑下的js文件 with open('xmSign.js',"r",encoding='utf-8') as f: js = f.read() # 通過compile命令轉成一個js對象 docjs = execjs.compile(js) # 調用js的function生成sign res = docjs.call('python',time) return res """獲取專輯一共有多少頁""" def getPage(): url = "https://www.ximalaya.com/ertong/424529/" html = requests.get(url,headers=headers).text # 創建BeautifulSoup對象 suop = BeautifulSoup(html,'lxml') # 實例化對象,使用lxml進行解析 # 根據屬性獲取 最大頁碼 max_page = suop.find("input",placeholder="請輸入頁碼").attrs["max"] return max_page response_list = [] """請求歌曲源地址""" def gethtml(): # 調用exec_js函數生成xm-sign xm_sign = exec_js() # 將生成的xm-sign添加到請求投中 headers["xm-sign"] = xm_sign max_page = getPage() for page in range(1,int(max_page)+1): url = "https://www.ximalaya.com/revision/play/album?albumId=424529&pageNum={}&sort=1&pageSize=30".format(page) # 下載 response= requests.get(url,headers=headers).text response = json.loads(response) response_list.append(response) """數據持久化""" def write_data(): # 請求歌曲地址拿到響應數據json gethtml() for res in response_list: data_list = res["data"]["tracksAudioPlay"] for data in data_list: trackName = data["trackName"] # 歌名 trackCoverPath = data["trackCoverPath"] # 封面地址 music_path = data["src"] # url print(trackName,trackCoverPath,music_path) write_data()