看过我的在线小说播放器博文的朋友问我,能不能详细介绍一下小说播放链接的获取。本篇博文将要介绍解密有声小说反爬,重点在于获得小说真实播放地址。

一.目标

1.首页

这是一个可以在线播放有声小说的网站,通过选择书籍,选择剧集最后实现有声小说的在线收听。

2.网页源代码

通过查看网页源代码,发现此网站为静态网站,所有网页内容都能在源代码中找到。

(网页源代码)

二.爬取详情页

1.查看详情页



可以看到,网页从上到下大致分为三部分,小说详情,小说简介,播放列表。

2.小说详情

打开开发者工具,摁下键盘组合键Ctrl+Shift+M,使用鼠标点击小说详情确定元素所在html标签,可以确定,小说详情在第一个class为book的div标签里。在这个标签中能得到小说封面、名称、类型、等级、状态、更新时间。

3.小说简介



在第二个class为book的div标签中能得到小说简介、作者、播音。

4.播放列表



在id为playlist的div标签中,能得到小说的播放列表,每集小说都在对应的li标签中,li标签下的a标签中包含小说剧集和播放网页地址(并非真正音频地址)。

三.爬取小说音频

1.确定数据加载方式

随便点击一个剧集,网页就会跳转到音频播放页面。

使用Ctrl+U查看网页源代码,未发现类似.mp3、.m4a格式音频地址,此时可以确定真实音频地址被加密了,或者是通过单独的接口异步加载进入网页。

2.寻找真实音频播放地址

开发者模式别关,刷新网页,点击网页的播放键,开始播放音频,将开发者工具筛选从All(所有)改成Media(媒体)。



通过筛选,发现此音频真实播放地址为:

https://t3344t.tingchina.com/yousheng/%E7%8E%84%E5%B9%BB%E5%A5%87%E5%B9%BB/%E6%96%97%E7%BD%97%E5%A4%A7%E9%99%863%E9%BE%99%E7%8E%8B%E4%BC%A0%E8%AF%B4_%E8%B5%9E%E6%89%AC/0001.mp3?key=e3f84d5d80bd806ae8b954cbf601978d_693500777

3.URL解码

上面的地址是什么哦,好乱啊,不要着急,这是URL编码,可以使用在线工具进行编码转换。



哦,原来网页将中文进行了编码转化。(我用的URL解码网站:http://www.jsons.cn/urlencode/)。

4.加密方式

回到网页源代码,下面这串Js吸引了我的注意。



于是去开发者工具中进行搜索函数名:FonHen_JieMa



发现此函数先是将传入的参数进行了字符串切割,然后遍历切割后的数组,使用String.fromCharCode()函数进行处理后,返回结果。

因为对Js了解不多,特地查了一下:

JavaScript fromCharCode()方法:

将Unicode 编码转为一个字符

var n = String.fromCharCode(65);

输出结果:A

此函数会将一个ASCII(Unicode)编码转成字符。

5.解密

将加密字符以*为分隔符进行切割,得到:

['', '51', '48', '49', '51', '48', '47', '121', '111', '117', '115', '104', '101', '110', '103', '47', '29572', '24187', '22855', '24187', '47', '26007', '32599', '22823', '-27066', '51', '-24679', '29579', '20256', '-29708', '95', '-29346', '25196', '47', '48', '48', '48', '49', '46', '109', '112', '51', '38', '57', '53', '53', '38', '116', '99']

去除掉空字符串,将数字输入到ASCII编码转换网站上,进行验证。







验证了前三位,再随机选取几个有符号数输入进行验证:







这里解释一下,为什么会有“负数”,此负数为有符号数,需要转化成原码然后进行还原:

对应的Python代码为:

chr((int(~int(s.replace("-", '')) & 0xffff) + 1))

非有符号数可以直接使用

chr(int(s))

直接获取对应的 ASCII 字符。

原码,补码和反码的知识可以参考:

原码,补码和反码

四.代码思路

针对加密参数,提出我的撰写代码思路。

五.源代码

Tingshubao_Spider.py

  1. import requests
  2. import re
  3. from urllib.parse import urljoin
  4. import urllib3
  5. from lxml import etree
  6. urllib3.disable_warnings()#解决warning
  7. class Tingshu_bao_spider:
  8. def do_get_request(self,url):
  9. """
  10. 发送网络请求,获取网页源代码
  11. :param url:
  12. :return:
  13. """
  14. headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
  15. "Referer":url}
  16. try:
  17. r=requests.get(url,headers=headers,timeout=6)
  18. if r.status_code==200:
  19. r.encoding=r.apparent_encoding
  20. html=r.text
  21. return html
  22. else:
  23. return False
  24. except:
  25. return False
  26. def get_novel_detail(self,sound_link):
  27. """
  28. 获取小说详情
  29. :param sound_link:
  30. :return:
  31. """
  32. novel_detail_item={}
  33. html=self.do_get_request(sound_link)
  34. if html:
  35. res=etree.HTML(html)
  36. name=res.xpath('//div[@class="book-cell"]/h1[@class="book-title"]/text()')
  37. if name:
  38. novel_detail_item['novel_name']=name[0].split("有声小说简介:")[0]
  39. else:
  40. novel_detail_item['novel_name']="未知"
  41. cover=res.xpath('//div[@class="book"]/img[@class="book-cover"]/@src')
  42. if cover:
  43. novel_detail_item['novel_cover']=urljoin(sound_link,cover[0])
  44. else:
  45. novel_detail_item['novel_cover']="未知"
  46. datas=res.xpath('//div[@class="book-rand-a"]//text()')
  47. if datas:
  48. novel_detail_item['novel_type'] = datas[1]
  49. novel_detail_item['novel_status'] = datas[3]
  50. novel_detail_item['novel_update_time'] = datas[-1]
  51. else:
  52. novel_detail_item['novel_type']="未知"
  53. novel_detail_item['novel_status'] = "未知"
  54. novel_detail_item['novel_update_time'] = "未知"
  55. #作者
  56. data2 = res.xpath('//div[@class="book-des"]/p/a/text()')
  57. if data2:
  58. novel_detail_item['novel_author'] = data2[0]
  59. novel_detail_item['novel_anchor'] = data2[-1]
  60. else:
  61. novel_detail_item['novel_author']="未知"
  62. novel_detail_item['novel_anchor']="未知"
  63. introduce = res.xpath('//div[@class="book-des"]/text()')
  64. if introduce:
  65. novel_detail_item['novel_introduce'] = introduce[0]
  66. else:
  67. novel_detail_item['novel_introduce']="未知"
  68. selector=res.xpath('//div[@id="playlist"]/ul/li')
  69. play_list=[]
  70. for data in selector:
  71. play_item={}
  72. novel_play_name=data.xpath("./a/@title")
  73. if novel_play_name:
  74. play_item["play_name"]=novel_play_name[0]
  75. else:
  76. play_item["play_name"]="NULL"
  77. novel_play_link = data.xpath("./a/@href")
  78. if novel_play_name:
  79. play_item["play_link"] = urljoin(sound_link,novel_play_link[0])
  80. else:
  81. play_item["play_link"]="NULL"
  82. play_list.append(play_item)
  83. novel_detail_item['play_list']=play_list
  84. return novel_detail_item
  85. else:
  86. return False
  87. def get_audio_play_link(self,detail_intro_link):
  88. """
  89. 获取小说播放链接地址
  90. :param detail_intro_link:
  91. :return:
  92. """
  93. html=self.do_get_request(detail_intro_link)
  94. if html:
  95. base_url="https://t3344t.tingchina.com/"
  96. aim_asciis=re.findall("FonHen_JieMa\('(.*?)'",html)
  97. if aim_asciis:
  98. sp = aim_asciis[0].split("*")
  99. res = ""
  100. for s in sp:
  101. if s != "":
  102. if "-" in s:
  103. res += chr((int(~int(s.replace("-", '')) & 0xffff) + 1))
  104. else:
  105. res += chr(int(s))
  106. aim_suffix = "/" + res.split('&')[0].split('/', 1)[-1]
  107. play_url=urljoin(base_url,aim_suffix)
  108. return play_url
  109. else:
  110. return False
  111. else:
  112. return False
  113. if __name__ == '__main__':
  114. t=Tingshu_bao_spider()
  115. aim_url='http://m.tingshubao.com/book/2267.html'
  116. print(t.get_novel_detail(aim_url))
  117. print(t.get_audio_play_link('http://m.tingshubao.com/video/?2267-0-0.html'))

六.结果

1.详情页

2.音频播放地址



有了真实播放地址,就能写代码,下载音频了。

七.总结

本次分析了一个有声小说网站,重点在于分析其小说详情页、音频播放地址,加密方式判断。思路、代码方面有什么不足欢迎各位大佬指正、批评!

Python3网络爬虫--爬取有声小说(附源码)的更多相关文章

  1. 如何利用Python网络爬虫爬取微信朋友圈动态--附代码(下)

    前天给大家分享了如何利用Python网络爬虫爬取微信朋友圈数据的上篇(理论篇),今天给大家分享一下代码实现(实战篇),接着上篇往下继续深入. 一.代码实现 1.修改Scrapy项目中的items.py ...

  2. 2019-04-23-Python爬取有声小说

    目录 Python爬取有声小说 摘要 1.获取下载链接 2.分析规律,循环爬取 3.保存到本地,批量命名 4.界面设计 5.效果展示 Python爬取有声小说 通过python爬取网站的资源,实现批量 ...

  3. 利用Python网络爬虫爬取学校官网十条标题

    利用Python网络爬虫爬取学校官网十条标题 案例代码: # __author : "J" # date : 2018-03-06 # 导入需要用到的库文件 import urll ...

  4. 使用scrapy爬虫,爬取17k小说网的案例-方法一

    无意间看到17小说网里面有一些小说小故事,于是决定用爬虫爬取下来自己看着玩,下图这个页面就是要爬取的来源. a 这个页面一共有125个标题,每个标题里面对应一个内容,如下图所示 下面直接看最核心spi ...

  5. 使用scrapy爬虫,爬取起点小说网的案例

    爬取的页面为https://book.qidian.com/info/1010734492#Catalog 爬取的小说为凡人修仙之仙界篇,这边小说很不错. 正文的章节如下图所示 其中下面的章节为加密部 ...

  6. Jsoup-基于Java实现网络爬虫-爬取笔趣阁小说

    注意!仅供学习交流使用,请勿用在歪门邪道的地方!技术只是工具!关键在于用途! 今天接触了一款有意思的框架,作用是网络爬虫,他可以像操作JS一样对网页内容进行提取 初体验Jsoup <!-- Ma ...

  7. 04 Python网络爬虫 <<爬取get/post请求的页面数据>>之requests模块

    一. urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求.其常被用到的子模块在Python3中的为urllib.request和urllib ...

  8. 如何用Python网络爬虫爬取网易云音乐歌曲

    今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将网易云歌词抓取下来已经不再话下了,在抓取歌词的时候在函数中传入了歌手ID和歌曲名两 ...

  9. 使用scrapy爬虫,爬取17k小说网的案例-方法二

    楼主准备爬取此页面的小说,此页面一共有125章 我们点击进去第一章和第一百二十五章发现了一个规律 我们看到此链接的  http://www.17k.com/chapter/271047/6336386 ...

  10. python网络爬虫&&爬取网易云音乐

    #爬取网易云音乐 url="https://music.163.com/discover/toplist" #歌单连接地址 url2 = 'http://music.163.com ...

随机推荐

  1. 用Docker搭建GIS本地化服务

    在Linux系统上安装docker 1. 脚本安装(安装的是最新版,也可能是不稳定版) wget -qO- https://get.docker.com/ | sh sudo usermod -aG ...

  2. Vue中使用model属性

    model属性接收两个参数 类型:{ prop?: string, event?: string } prop 也就是调用该组件的父组件中使用v-model指令绑定的属性 event 对应的是修改pr ...

  3. saml login的流程

    用户会访问首页/, 然后进入到指定的一个URL, 就是admin在site-settings里面的设置的那个地址, 发现权限不够,进入到403accesslogin, 然后调用user4032logi ...

  4. Windows支持多个远程连接

    1.点击 开始-->运行-->输入"gpedit.msc",进入本地组策略编辑器 2.点击 计算机配置-->管理模板-->Windows组件-->远程 ...

  5. WPF_MVVM框架(5)

    1.NuGet引用MVVM框架包 引入该框架包之后, 默认会在目录下创建ViewModel层的示例代码 2.第二步, 通过在MainViewModel中创建一些业务代码, 将其与MainWindow. ...

  6. node_modules/canvas npm ERR! command failed

    Installing packages. This might take a couple of minutes.Installing react, react-dom, and react-scri ...

  7. 2022.11.15 NOIP2022 模拟赛十

    炸弹威力 Source:洛谷 P6036. 记 \(f_{i,0/1}\) 表示第 \(i\) 个位置为 \(0/1\) 的答案个数,有 DP 转移: \[\begin{aligned} (1-p_i ...

  8. unix:///var/run/supervisor.sock no such file报错解决办法

    报错 unix:///var/run/supervisor.sock no such file 原因 /var/run/supervisor.sock已被清理. 解决办法 关闭supervisor:p ...

  9. 02 Spark架构与运行流程

    1. 为什么要引入Yarn和Spark. YARN优势1.YARN的设计减小了JobTracker的资源消耗,并且让监测每一个Job子任务(tasks)状态的程序分布式化了,更安全.更优美. 2.在新 ...

  10. 用Python把PDF文件转换成Word文档

    首先,下载所需要的库 1 :pdfminer   安装库命令: pip install pdfminer3k 2:  docx     安装库命令: pip install python_docx 开 ...