爬虫高级必然JS逆向,QQ音乐爬虫就是一个很好的练手,读完学会了直接在你女朋友面前装一手,读完你将收获到,QQ音乐JS逆向,sign参数获取,songmid参数获取,vkey参数获取,selenium自动化解析,用python解析执行js代码。


效果图:


页面分析:

  • 当我们打开QQ音乐的时候,你想要播放歌曲,页面会强制你登入账号,才能调用网页的播放器, 这是一个重要点, 所以后面的参数中,我们要加入账号信息, 这个爬虫是不能爬取vip视频的,凡是标题带爬vip视频的,一定要仔细看看, 腾讯这么大公司还会让你写个小爬虫就随便拿掉数据的,这不是瞎搞啊,所以我将的只是获取非会员歌曲的方式。
  • 那下面就一步一步的开始吧!

1. 初步分析

首先我们随意的播放一些歌曲,如下:

在调试中,我们可以找到这样的js文件,(具体怎么找,刷新一直点看呗,或者你眼尖可以看链接参数,没啥经验,就一个个点看看, 后面记得参数就可以直接用过滤器或者搜索 ),找到如下:

上面的框是这首歌对应的链接,复制打开在浏览器,就可以直接播放,下面的框是请求携带的参数,区别二首歌如下:

ps: 对于这个连接注意一点, 参数没有带r, 所以你找到的参数带r的,没有用,错了,对着我图仔细看看。

发现了吧,也就是vkey参数发现了变化。所以这个vkey参数是一个关键点。
那下面我们寻找vkey。


2. 寻找vkey

这个时候,我们就可以直接用过滤器了,因为知道是参数vkey, 如下:

在 preview 中,我找到了vkey参数,但是细心的你会发现,这里直接就有一个网址参数, purl 对比之前的歌曲链接, 你会发现,前面少了一些而已, 少了 https://u.y.qq.com/cgi-bin/musics.fcg? 到时候直接加上去就得了, 所以不碍事,现在我们看一下这个链接的参数构成,如下:

对比分析发现, 有用的参数 sign, -, longinUin, data , 其他参数可有可无, 其中动态变化的参数是 sign 和 songmid, 那现在我们只需要找到这二个参数在哪里就行了。


3. 寻找songmid:

关于这个songmid,真是要了我的命, 我一直在播放界面中去找, 一直捣腾,结果屁都没有,无意中,我在列表区打开了调试, 然后我就发现了这个songmid庐山真面目了,如下:

右边箭头中 a标签里面最后一段就是songmid,感谢它直接拼接到浏览器中,那就好办了,直接爬它,然后和对应的歌手啊,歌曲名啊,放在一个字典或者元组里面,方便后面操作, 对于这个页面的爬取,不能直接用request去爬的,动态js渲染,得用selenium去爬,后面会讲到, 在这里,我们把href 进行处理就可以拿到songmid了。


4. 寻找sign:

sign参数应该是QQ音乐最变态的一个参数了,极度难找,但是最后还是被我找到了,没有用,兵来将挡水来土掩,还是我行。

在之前的vkey的图片里面,我们点击他对应的js文件,如下:

然后可视化打开,搜索sign参数,最后找到像这样。

在这些参数上都打上断点, 开始调试, 我们发现 sign参数,是由一个函数 getSecuritySign() 返回的, 对的,一开始我也是这样认为的,调试中,我们可以进入到这个函数,打开发现是一段js文件,如下:

直接把这个复制文件到自己电脑里面, python第三方库 execjs 可以运行js文件或者js代码, 安装 pip install PyExecJS 想了解的可以百度,或者直接阅读源码。

我们直接把这个文件调用运行,是不可以的,会发现n, window, sign 都没有定义, 所以我们需要进行处理,处理之后,然后模拟加密之后,结果居然错了,sign一直对不上,这就很奇怪,差不多我是从昨天下午一直到现在纠结这个sign参数, 期间我debug了很久很久,最后我放弃了, 开始百度寻找答案, 感谢大佬,参考大佬文章, 在他的一篇文章中, 我知道了sign的获取不仅仅是直接调用这个函数, 还需要其他的操作,如下:

补充之前没有定义的参数, 然后调用 __sign_hash_20200305加密函数,最后发送这个sign参数, 最后我也是拿到了这个参数,这里面的参数data就是之前我们图片中的携带参数data, 可以参考前面的图片,到这里我们就获取到了sign参数。


爬虫高级必然JS逆向,QQ音乐爬虫就是一个很好的练手,读完学会了直接在你女朋友面前装一手,读完你将收获到,QQ音乐JS逆向,sign参数获取,songmid参数获取,vkey参数获取,selenium自动化解析,用python解析执行js代码。

爬虫思路:

既然这些参数我们都知道怎么获取的了,那么编写这个代码也就简单多了, 这次就不发送邮箱给女朋友了,直接输出在控制台得了, 有需要的自行扩展, 甚至你还可以用scrapy扩展到爬取全站的音乐资源, 但是最好别这样,文明爬虫,别搞事情。

  • songmid 的获取我们需要导入selenium ,然后搭配headless, useagent
  • sign 我们需要使用execjs执行js文件获取
  • vkey(purl) 我们需要使用构造好的表单参数请求网址
  • down_url 我们只需要请求网址,然后下载到本地就行了。

编写爬虫。

Js文件放不进来,太大了, 可以自己在浏览器中获取,实在不行找我吧。。

代码:

init

import requests
from urllib.parse import urlencode
from get_useragent import GetUserAgentCS
import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from lxml import etree
import time
import execjs  # 执行jsclass Getparams(object):"""参数需要逆推,在第一个get_mp3_ur中,参数 vkey 是会变化的,所以我们需要拿到vkey参数 和 C4000....... m4a 参数继续分析其他页面, 看看怎么拿到这些参数"""def __init__(self):self.ua = GetUserAgentCS().get_user()#  setting the selenium headlessself.chrome_options = Options()self.chrome_options.add_argument('--headless')self.chrome_options.add_argument('--disable-gpu')self.browser = None# 添加随机请求头 并完成设置self.SeleniumUserAgent()self.SeleniumSettingEnd()# 测试代码# ----------------------self.get_mp3_url = 'https://isure.stream.qqmusic.qq.com/C4000000CZcC0Yu576.m4a?'self.params = {"guid": "62749440", "vkey": "CD3C2A1C153884C4A10594EBA5A1070036CDB6107A2DEB9FE139C3C9""D4F73CF44AD0711941B2B4D33B1A76D52DFAE72231F3BAF1FFB05FC5","uin": "2936", "fromtag": "66",}# ---------------------self.path = os.path.join(os.path.dirname(__file__), 'QQ音乐下载/')self.headers = {"user-agent": self.ua}self.down_mp3_url = 'https://u.y.qq.com/cgi-bin/musics.fcg?'# 暂时先用一页  有需要扩展可以全站爬取self.homepage = 'https://y.qq.com/n/yqq/playlist/7278178798.html'# down url requestself.down_url = 'https://ws.stream.qqmusic.qq.com/'self.name_singer_mid = []self.isExist(path=self.path)

分不清网址是哪个的, 回头看, 自己记下来那些网址的前缀。

获取songmid:

    def using_selenium_to_get_songmid(self):"""using the selenium to spider the page nowTODO: The function maybe using add the page cookiesreturn  fill the self.list"""self.browser.get(self.homepage)time.sleep(1)  # 等待js渲染完成html = etree.HTML(self.browser.page_source)song_name = html.xpath('//ul[@class="songlist__list"]/li/div/div[3]/span/a/@title')song_tags_a = html.xpath('//ul[@class="songlist__list"]/li/div/div[3]/span/a/@href')# https://y.qq.com/n/yqq/song/002d6Cow334MPL.html  类似这样的song_mid = ["".join(i.strip(".html").split("/")[-1]) for i in song_tags_a]song_singer = html.xpath('//ul[@class="songlist__list"]/li/div/div[4]/a/text()')self.name_singer_mid = list(zip(song_name, song_singer, song_mid)).copy()# print(list(zip(song_name, song_singer, song_mid)))

获取sign:

  def get_sign(self, datas):with open('D:\pyth\网络爬虫设计\QQMp3spider\getsign.js', 'r') as fr:course = fr.read()js = execjs.compile(course)sign = js.call('getSecuritySign', datas)# a = Sim_hash(data=datas)# sign += a.jiami(a.get_sign())# ss = 'CJBPACrRuNy7' + json.dumps(datas)# ss = 'CJBPACrRuNy7' + JSON.stringify(data);return sign

构造参数获取vkey(purl):

    def get_down_mp3_url(self, song_mid=None):"""params : song_midjust enter the params"""try:if not song_mid or not isinstance(song_mid, str):raise Exception("The song_mid is error, you enter a None or  list, ""you song_mid is ", song_mid, "the type is ", type(song_mid))except Exception as e:print("You can run the function again !", e)params = {"-": "getplaysongvkey3441060389750814","g_tk": "829763618",'sign': '',"loginUin": "884427640","data": {'req': {"module": "CDN.SrfCdnDispatchServer", "method": "GetCdnDispatch","param": {"guid": "62749440", "calltype": 0, "userip": ""}},"req_0": {"module": "vkey.GetVkeyServer", "method": "CgiGetVkey","param": {"guid": "62749440", "songmid": [str(song_mid)], "songtype": [0],"uin": "884427640", "loginflag": 1, "platform": "20"}},"comm": {"uin": 884427640, "format": "json", "ct": 24, "cv": 0}}}sign = self.get_sign(params['data'])print(sign)params['sign'] = sign# 对网址进行一部分微处理url = self.down_mp3_url + urlencode(params, encoding='UTF-8')url = url.replace("+", "")url = url.replace("%27", "%22")# encode the url using utf8print(url)r = requests.get(url, headers=self.headers)time.sleep(0.7)if r.status_code == 200:# 分析出接口网址try:purl = r.json().get("req_0")['data']['midurlinfo'][0]["purl"]return self.down_url + purlexcept Exception as e:print("出现了一点错误,我们正在重试! ", e)time.sleep(1)self.get_down_mp3_url(song_mid=song_mid)else:raise Exception("down request error  ", r.status_code)

这里要注意我们构造的url是有问题的, 存在编码不匹配, 替换一下就行了。

打印下载:

   def print_list(self):"""print the name_singer_mid the listyou can choose a music download or choose all music"""print('正在加载歌曲列表,请等待........')self.using_selenium_to_get_songmid()print("- " * 10, "QQMusic DownLoad", "- " * 10)print(f'序号\t\t歌曲\t\t歌手')for index, content in enumerate(self.name_singer_mid):print(f'{index + 1}\t\t{content[0]}\t\t{content[1]}')msg = """PS: 输入可以单个或者多个输出,若全部下载,第一个值请输入字母 'a'单个输入,输入结束后回车多个输入,输入以空格隔开序号,后回车请输入你的选项:"""flag = input(msg).split()if len(flag) == 1 and flag[0] == "a":self.down_mp3(self.name_singer_mid, islist=True)elif len(flag) >= 2:# TODO: 生成一个零时数组,遍历返回k = [self.name_singer_mid[int(i) - 1] for i in flag]self.down_mp3(k, islist=True)elif len(flag) == 1:self.down_mp3(self.name_singer_mid[int(flag[0]) - 1], islist=False)def down_mp3(self, url_list, islist=False):"""params: url_list  , using the url to down  load the music.mp3islist  bool  False/ True"""print("正在下载中, 请稍等.......")if not islist:self.down(mid_path=url_list[1], song_mid=url_list[2], song_name=url_list[0])elif islist:for i in url_list:self.down(mid_path=i[1], song_mid=i[2], song_name=i[0])def down(self, mid_path, song_mid, song_name):"""down function """self.isExist(path=(self.path + str(mid_path) + "/"))url = self.get_down_mp3_url(song_mid=song_mid)r = requests.get(url, headers=self.headers)if r.status_code == 200:filename = str(song_name).strip() + ".mp3"with open(filename, 'ab') as fw:fw.write(r.content)print(f'下载ok, 保存ok ,', filename)

爬虫高级必然JS逆向,QQ音乐爬虫就是一个很好的练手,读完学会了直接在你女朋友面前装一手,读完你将收获到,QQ音乐JS逆向,sign参数获取,songmid参数获取,vkey参数获取,selenium自动化解析,用python解析执行js代码。

全部代码:

# -*- coding :  utf-8 -*-
# @Time      :  2020/9/24  21:52
# @author    :  沙漏在下雨
# @Software  :  PyCharm
# @CSDN      :  https://me.csdn.net/qq_45906219
import requests
from urllib.parse import urlencode
from get_useragent import GetUserAgentCS
import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from lxml import etree
import time
import execjs  # 执行jsclass Getparams(object):"""参数需要逆推,在第一个get_mp3_ur中,参数 vkey 是会变化的,所以我们需要拿到vkey参数 和 C4000....... m4a 参数继续分析其他页面, 看看怎么拿到这些参数"""def __init__(self):self.ua = GetUserAgentCS().get_user()#  setting the selenium headlessself.chrome_options = Options()self.chrome_options.add_argument('--headless')self.chrome_options.add_argument('--disable-gpu')self.browser = None# 添加随机请求头 并完成设置self.SeleniumUserAgent()self.SeleniumSettingEnd()# 测试代码# ----------------------self.get_mp3_url = 'https://isure.stream.qqmusic.qq.com/C4000000CZcC0Yu576.m4a?'self.params = {"guid": "62749440", "vkey": "CD3C2A1C153884C4A10594EBA5A1070036CDB6107A2DEB9FE139C3C9""D4F73CF44AD0711941B2B4D33B1A76D52DFAE72231F3BAF1FFB05FC5","uin": "2936", "fromtag": "66",}# ---------------------self.path = os.path.join(os.path.dirname(__file__), 'QQ音乐下载/')self.headers = {"user-agent": self.ua}self.down_mp3_url = 'https://u.y.qq.com/cgi-bin/musics.fcg?'# 暂时先用一页  有需要扩展可以全站爬取self.homepage = 'https://y.qq.com/n/yqq/playlist/7278178798.html'# down url requestself.down_url = 'https://ws.stream.qqmusic.qq.com/'self.name_singer_mid = []self.isExist(path=self.path)def SeleniumUserAgent(self):"""Setting the selenium the user-agent"""self.chrome_options.add_argument("lang=zh_CN.UTF-8")  # setting the language (chinese)self.chrome_options.add_argument(f"user-agent={self.ua}")def SeleniumSettingEnd(self):"""Setting the selenium  if end"""# As: selenium Chrome Settingself.browser = webdriver.Chrome(options=self.chrome_options)def isExist(self, path=None):"""mkdir"""print('create and  into ', path)path = path.strip()if not os.path.exists(path):os.mkdir(path)os.chdir(path)else:os.chdir(path)def using_selenium_to_get_songmid(self):"""using the selenium to spider the page nowTODO: The function maybe using add the page cookiesreturn  fill the self.list"""self.browser.get(self.homepage)time.sleep(1)  # 等待js渲染完成html = etree.HTML(self.browser.page_source)song_name = html.xpath('//ul[@class="songlist__list"]/li/div/div[3]/span/a/@title')song_tags_a = html.xpath('//ul[@class="songlist__list"]/li/div/div[3]/span/a/@href')# https://y.qq.com/n/yqq/song/002d6Cow334MPL.html  类似这样的song_mid = ["".join(i.strip(".html").split("/")[-1]) for i in song_tags_a]song_singer = html.xpath('//ul[@class="songlist__list"]/li/div/div[4]/a/text()')self.name_singer_mid = list(zip(song_name, song_singer, song_mid)).copy()# print(list(zip(song_name, song_singer, song_mid)))def get_sign(self, datas):with open('D:\pyth\网络爬虫设计\QQMp3spider\getsign.js', 'r') as fr:course = fr.read()js = execjs.compile(course)sign = js.call('getSecuritySign', datas)# a = Sim_hash(data=datas)# sign += a.jiami(a.get_sign())# ss = 'CJBPACrRuNy7' + json.dumps(datas)# ss = 'CJBPACrRuNy7' + JSON.stringify(data);return signdef get_down_mp3_url(self, song_mid=None):"""params : song_midjust enter the params"""try:if not song_mid or not isinstance(song_mid, str):raise Exception("The song_mid is error, you enter a None or  list, ""you song_mid is ", song_mid, "the type is ", type(song_mid))except Exception as e:print("You can run the function again !", e)params = {"-": "getplaysongvkey3441060389750814","g_tk": "829763618",'sign': '',"loginUin": "884427640","data": {'req': {"module": "CDN.SrfCdnDispatchServer", "method": "GetCdnDispatch","param": {"guid": "62749440", "calltype": 0, "userip": ""}},"req_0": {"module": "vkey.GetVkeyServer", "method": "CgiGetVkey","param": {"guid": "62749440", "songmid": [str(song_mid)], "songtype": [0],"uin": "884427640", "loginflag": 1, "platform": "20"}},"comm": {"uin": 884427640, "format": "json", "ct": 24, "cv": 0}}}sign = self.get_sign(params['data'])print(sign)params['sign'] = sign# 对网址进行一部分微处理url = self.down_mp3_url + urlencode(params, encoding='UTF-8')url = url.replace("+", "")url = url.replace("%27", "%22")# encode the url using utf8print(url)r = requests.get(url, headers=self.headers)time.sleep(0.7)if r.status_code == 200:# 分析出接口网址try:purl = r.json().get("req_0")['data']['midurlinfo'][0]["purl"]return self.down_url + purlexcept Exception as e:print("出现了一点错误,我们正在重试! ", e)time.sleep(1)self.get_down_mp3_url(song_mid=song_mid)else:raise Exception("down request error  ", r.status_code)def print_list(self):"""print the name_singer_mid the listyou can choose a music download or choose all music"""print('正在加载歌曲列表,请等待........')self.using_selenium_to_get_songmid()print("- " * 10, "QQMusic DownLoad", "- " * 10)print(f'序号\t\t歌曲\t\t歌手')for index, content in enumerate(self.name_singer_mid):print(f'{index + 1}\t\t{content[0]}\t\t{content[1]}')msg = """PS: 输入可以单个或者多个输出,若全部下载,第一个值请输入字母 'a'单个输入,输入结束后回车多个输入,输入以空格隔开序号,后回车请输入你的选项:"""flag = input(msg).split()if len(flag) == 1 and flag[0] == "a":self.down_mp3(self.name_singer_mid, islist=True)elif len(flag) >= 2:# TODO: 生成一个零时数组,遍历返回k = [self.name_singer_mid[int(i) - 1] for i in flag]self.down_mp3(k, islist=True)elif len(flag) == 1:self.down_mp3(self.name_singer_mid[int(flag[0]) - 1], islist=False)def down_mp3(self, url_list, islist=False):"""params: url_list  , using the url to down  load the music.mp3islist  bool  False/ True"""print("正在下载中, 请稍等.......")if not islist:self.down(mid_path=url_list[1], song_mid=url_list[2], song_name=url_list[0])elif islist:for i in url_list:self.down(mid_path=i[1], song_mid=i[2], song_name=i[0])def down(self, mid_path, song_mid, song_name):"""down function """self.isExist(path=(self.path + str(mid_path) + "/"))url = self.get_down_mp3_url(song_mid=song_mid)r = requests.get(url, headers=self.headers)if r.status_code == 200:filename = str(song_name).strip() + ".mp3"with open(filename, 'ab') as fw:fw.write(r.content)print(f'下载ok, 保存ok ,', filename)def start(self):"""start yourself  demo"""url = self.get_mp3_url + urlencode(self.params)r = requests.get(url, headers=self.headers)if r.status_code == 200:with open("勿忘.mp3", 'wb') as fw:fw.write(r.content)print("down load successful !")a = Getparams()
a.print_list()

此文转载文,著作权归作者所有,如有侵权联系小编删除!

原文地址:https://blog.csdn.net/qq_45906219/article/details

完整项目代码或者视频教程点这里

QQ音乐JS逆向爬虫,我用python全都爬!相关推荐

  1. QQ音乐JS逆向分析参数,爬它,多图预警

    昨天看一个哥们的文章说是MD5加密,自己试了试,不知道怎么出错了,所以就老老实实JS逆向了,但真的是MD5加密 分析一下要获得的参数 这次用逆推的方式,应该好理解 1.开发者模式,媒体C40000开头 ...

  2. python爬取qq音乐评论_爬虫:QQ音乐评论

    QQ音乐评论 有些小伙伴反馈,对于爬虫的完整流程,还是不清楚,这边就按顺序,给大家梳理一下 反爬 首先查看一下,我们要爬取的网页,是否反爬(各种侵害人家服务器的事情,我们不能干) QQ音乐网址:htt ...

  3. NO.35——qq音乐全站分布式爬虫(一)

    一.目的 qq音乐提供免费在线试听,但是下载需要付费,通过开发爬虫,绕过付费环节,直接下载我们需要的歌曲. 二.方法 爬取对象是web端qq音乐,爬取范围是全站的歌曲信息,爬取方式是在歌手列表下获取每 ...

  4. 手把手操作JS逆向爬虫入门(一)

    本文爬取的网站如下(可以找解密工具解码) aHR0cHM6Ly9uZXdyYW5rLmNuLw== 爬取的内容为网站的资讯情报版块的新闻资讯 鼠标点击翻页,在开发者工具中查看请求包,很容看出请求地址和 ...

  5. js逆向爬虫实战之快手第三方平台之获取登录cookies!

    爬虫js逆向系列 我会把做爬虫过程中,遇到的所有js逆向的问题分类展示出来,以现象,解决思路,以及代码实现.我觉得做技术分享,不仅仅是要记录问题,解决办法,更重要的是要提供解决问题的思路.怎么突破的, ...

  6. 如何用python抓取qq音乐_手把手教你使用Python抓取QQ音乐数据(第二弹)

    [一.项目目标] 通过Python爬取QQ音乐数据(一)我们实现了获取 QQ 音乐指定歌手单曲排行指定页数的歌曲的歌名.专辑名.播放链接. 此次我们在之前的基础上获取QQ音乐指定歌曲的歌词及前15个精 ...

  7. 如何用python抓取qq音乐_手把手教你使用Python抓取QQ音乐数据(第三弹)-阿里云开发者社区...

    [一.项目目标] 通过手把手教你使用Python抓取QQ音乐数据(第一弹)我们实现了获取 QQ 音乐指定歌手单曲排行指定页数的歌曲的歌名.专辑名.播放链接. 通过手把手教你使用Python抓取QQ音乐 ...

  8. python爬取qq音乐评论_教你用Python爬去QQ音乐评论

    有态度地学习 去年夏天,好像于我而言,重要的事就是毕业来临,从此踏上了搬砖之路,从学校到职场,之间身份的转变,让我又多了一份责任.当然还有一段感情经历,现在回头去看,只能说且行且珍惜,或许以后未必能再 ...

  9. 如何用python抓取qq音乐_手把手教你使用Python抓取QQ音乐数据

    [一.项目目标] 获取 QQ 音乐指定歌手单曲排行指定页数的歌曲的歌名.专辑名.播放链接. 由浅入深,层层递进,非常适合刚入门的同学练手. [二.需要的库] 主要涉及的库有:requests.json ...

最新文章

  1. SYN攻击SYN Attack
  2. javascript 的面向对象特性参考
  3. 大数据互联网架构阶段 数据库三范式与反范式
  4. 你真的了解Python吗?这篇文章可以让你了解90%,赶紧收藏!
  5. 有了优秀的可临摹PSD分层模板|瞬间提升海报质感!
  6. POJ 1113 Wall 求凸包
  7. DT大数据梦工厂 第72,73讲
  8. mac 生成公钥和私钥
  9. Stata: 空间面板数据模型及Stata实现
  10. UE4脸部捕捉关键函数使用
  11. 菜鸟学院~沉寂近30年后火了!存内计算如何打破AI算力瓶颈?
  12. 各种手段终于将土豆视频url请求找到了
  13. http-proxy-middleware
  14. 用canvas 绘制一个灰太狼
  15. linux maskrom模式,微雪电子RK3308主板CC启动模式介绍
  16. leetcod_1_两数之和
  17. 模电笔记1:半导体基础知识
  18. 美团面试 java后端开发
  19. 新型敏捷硬件设计语言---Chisel初识
  20. 建立一个Point类,包含数据成员x,y,实现需要的成员函数,并设计main函数完成测试

热门文章

  1. 北理工c语言压缩文本文件,北理工C语言2(推荐文档).docx
  2. 通信原理简明教程 | 数字基带传输
  3. Alter对话框处理
  4. vscode前端环境(html+css+javascript)的配置
  5. 移动app——“免费”才是王道
  6. python元组转字符串_python3字符串和字典、集合、元组的相互转换 | 吴老二
  7. c语言背包问题装字母,C语言动态规划之背包问题详解
  8. 你会阅读Java源码吗
  9. 《深入理解LTE-A》读书笔记之LTE 帧结构
  10. IO模型-异步I/O模型