正文
我们可以控制台输出一下u和c
所以我们就知道了sign实际是加密了请求的其他参数
一开始我误以为是单纯的MD5所以卡了好久(还进入函数内部看他具体是怎么实现的看的一头雾水)
其实代码已经告诉用的是
createHmac(“md5”, “fpMn12&38f_2e”)
查了下Hmac发现就是一种现成的算法,还有不同的模式MD5是其中一种,需要一个秘钥
这里什么都告诉你了,用Hmac-md5秘钥是fpMn12&38f_2e
找个在线加密的网站试了下,果然和刚才控制台输出的一样
python的话需要import hmac这个库 import hmac import time base_url = “https://audio.qingting.fm” bookid = “294280” id = “11590788” access_token = “” qingting_id =“” timestamp = str(round(time.time()*1000)) data = f"/audiostream/redirect/{bookid}/{id}?access_token={access_token}&device_id=MOBILESITE&qingting_id={qingting_id}&t={timestamp}" message = data.encode(‘utf-8’) key = “fpMn12&38f_2e”.encode(‘utf-8’) sign = hmac.new(key, message, digestmod=‘MD5’).hexdigest() whole_url = base_url+data+“&sign=”+sign print(whole_url)
得到一个音频可以做到了剩下的就是得到一堆了,其实我们得到每个音频的id就可以了
我请求的是这个接口
info_api = ‘https://i.qingting.fm/capi/channel/{self.bookid}/programs/{self.version}?curpage={str(page)}&pagesize=30&order=asc’
version在声书主页的源代码中,只要改curpage就可以翻页了
完整源码
import requests import re import hmac import time from tqdm import tqdm from bs4 import BeautifulSoup import os import json import sys import urllib3 urllib3.disable_warnings() class QingTing(): def init(self,user_id,password,bookurl,ifLogin): self.ifLogin = ifLogin self.user_id = user_id self.password = password self.session = requests.session() self.session.headers.update({‘user-agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36’}) self.login_url = “https://u2.qingting.fm/u2/api/v4/user/login” self.qingting_id = ‘’ self.access_token = ‘’ self.bookurl = bookurl
self.bookurl = ‘https://www.qingting.fm/channels/257790’
self.bookid = self.bookurl.split(‘/’)[-1] self.version = ‘’ self.qingtinghost = ‘https://audio.qingting.fm’ self.save_path = ‘’ self.bookname = ‘’ def login(self,user_id,password): data = { ‘account_type’: ‘5’, ‘device_id’: ‘web’, ‘user_id’: user_id, ‘password’: password } response = self.session.post(self.login_url,data=data,verify=False) if response.status_code==200: temp = response.json() errorno = temp[‘errorno’] errormsg = temp[‘errormsg’] if errorno == 0: print(‘login successful!’,‘登录成功!’) data = temp[‘data’] self.qingting_id = data[‘qingting_id’] self.access_token = data[‘access_token’] else: print(‘Login failed’,‘登录失败’) print(errormsg) time.sleep(10) sys.exit(0) def __get_version(self): response = self.session.get(url=self.bookurl,verify=False) if response.status_code==200: soup = BeautifulSoup(response.text,‘lxml’) temp_bookname = soup.select(‘div.album-info-root > div.top > div.info.right > h1’)[0].string replaced_pattern = ‘[\/😗?"<>|]’ self.bookname = re.sub(replaced_pattern,’ ',temp_bookname,flags=re.M +re.S) if not os.path.exists(self.bookname): os.makedirs(self.bookname) matched = re.search(‘“version”:“(\w+)”’,response.text,re.S) if matched: version = matched.group(1) self.version = version
return version
def __get_total_page(self): self.__get_version() page = 1 info_api = f’https://i.qingting.fm/capi/channel/{self.bookid}/programs/{self.version}?curpage={str(page)}&pagesize=30&order=asc’ response = self.session.get(info_api,verify=False) if response.status_code==200: temp = response.json() total = temp[‘data’][‘total’] total_page = int(int(total)/30)+1 return total,total_page def get_book_info(self): total,total_page = self.__get_total_page() print(self.bookname,‘共{}集’.format(total)) for page in range(1,total_page+1): info_api = f’https://i.qingting.fm/capi/channel/{self.bookid}/programs/{self.version}?curpage={str(page)}&pagesize=30&order=asc’ response = self.session.get(info_api,verify=False) programs = response.json()[‘data’][‘programs’] for program in programs:
print(program[‘id’],program[‘title’])
yield program def get_src(self,id): bookid = self.bookid access_token = self.access_token qingting_id =self.qingting_id timestamp = str(round(time.time()*1000)) data = f"/audiostream/redirect/{bookid}/{id}?access_token={access_token}&device_id=MOBILESITE&qingting_id={qingting_id}&t={timestamp}" message = data.encode(‘utf-8’) key = “fpMn12&38f_2e”.encode(‘utf-8’) sign = hmac.new(key, message, digestmod=‘MD5’).hexdigest() whole_url = self.qingtinghost+data+“&sign=”+sign return whole_url def downloadFILE(self,url,name): resp = self.session.get(url=url,stream=True,verify=False) if resp.headers[‘Content-Type’] ==‘audio/mpeg’: content_size = int(int(resp.headers[‘Content-Length’])/1024) with open(name, “wb”) as f: print(“Pkg total size is:”,content_size,‘k,start…’) for data in tqdm(iterable=resp.iter_content(1024),total=content_size,unit=‘k’,desc=name): f.write(data) print(name , “download finished!”) else: errorno = resp.json()[‘errorno’] errormsg = resp.json()[‘errormsg’] print(‘没有权限下载,请登录已购此音频的账号。’) print(‘errorno:’,errorno,errormsg) def run(self): if self.ifLogin: self.login(self.user_id,self.password) programs = self.get_book_info() count = 0 for program in programs: count+=1 try: id = program[‘id’] title = str(count).zfill(4)+’ ‘+program[‘title’]+’.m4a’ if not self.bookname ==‘’: title = os.path.join(self.bookname,title)
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
三、全套PDF电子书
书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。
四、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
五、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。