最近这段时间,我用喜马拉雅听了 鬼吹灯之精绝古城 、 斗罗大陆 。与看书、带影像的电视和电影相比,我更愿意用听的方式学习。
听书是一种重要的学习方式。至少,我自己很喜欢。一般来说,学习的方式有两种,即视觉和听觉。有些人适合阅读,记忆更深刻;有些人适合听书,理解更容易。
上下班路上听书特别充实。每周末,我提前下载好要听的书,不管走路、等车还是坐车,一直听。早晚两个小时的时间,能听很多。工作一天,站在车里,闭目养神,听着自己喜欢的书,也是一种人生享受。
听书就像一个好朋友在为你讲故事,精彩的地方令人入迷,同时听书也有许多好处:
1、保护眼睛。这是最重要的。与读书或在手机上看信息相比,听书可以保护眼睛,避免长年面对移动设备造成的伤害,让眼睛轻松很多。
2、如果你工作忙碌,经常处于奔波的状态,相对完整的个人时间不多,那听书很适合你。上下班路上,出差、旅行的途中,都可以用听书的方式学习。相对来说,阅读则很难完全满足。
3、互联网时代,碎片化、浅阅读切碎了我们的注意力和思考时间。
说了那么多,就是为了引出今天的主题,爬取56听书网,大家可以通过代码下载自己喜欢的作品,话不多说步入正文。之所以没有爬取喜马拉雅,是因为之前有作品介绍过, ~~传送链接~~
1.输入网址链接:
http://www.ting56.com/
2.随便选择了一个作品,以该作品为例,链接如下:
http://www.ting56.com/mp3/21163.html
3.在该页面下,我们通过以下规则可以获取:
# 书名
name = list999.xpath('//div[@class="tit"]/h1/text()')
# 所有章节链接
lists = list999.xpath('//*[@id="vlink_1"]/ul/li/a/@href')
# 章节数量
count = int(list999.xpath('count(//*[@id="vlink_1"]/ul/li)'))
通过上面的规则,我们可以成功的获取到每个章节的链接,这样的话,接下来我们分析下章节页面的详情即可,点击播放,我们可以看出发送了一个音频链接的请求。
但是我们通过 CTRL + U 查看源码,并没有查看到所谓的音频链接,这就说明了,链接是数据加密渲染出来的,在页面查找下能看到:
我们明显可以看到一个 datas 的值,而 datas2 可以看出他是该页面的标题,所以只要搞明白 datas 的值是怎么来的就行了。看下图:
由此可以得出一个结论,里面的数字都是对应的ASCII字符,我们可以通过如下方法获得真正的链接的值:
def get_con(url):
xml = get_url(url)
ssrl = re.search('var datas=\S*', xml)[0].split('*') # 正则获取加密链接数组并且按照*号分割
print(ssrl)
murl = ''
for i in range(1, int(len(ssrl)) - 1): # 遍历获取的数字并转换成ASCII码然后拼接链接!
s = ssrl[i]
# print(s)
p = chr(int(s))
# print(p)
murl += p
# print(murl)
ms = murl.split('&') # 分割拼接出来的链接,取得包含音频链接的的列表
# print(ms)
# print(1222)
return ms
到目前为止,我们就走通了爬取一个作品的所有思路,具体代码如下:
# coding:utf-8
# __auth__ = "maiz"
import os
import requests
from lxml import etree
import re
def get_url(url):
# 获取源码
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'}
res = requests.get(url, headers=headers)
res.encoding = res.apparent_encoding
if res.status_code == 404:
print('获取源码失败,退出程序')
os._exit(0)
else:
return res.text
def get_con(url):
xml = get_url(url)
ssrl = re.search('var datas=\S*', xml)[0].split('*') # 正则获取加密链接数组并且按照*号分割
print(ssrl)
murl = ''
for i in range(1, int(len(ssrl)) - 1): # 遍历获取的数字并转换成ASCII码然后拼接链接!
s = ssrl[i]
# print(s)
p = chr(int(s))
# print(p)
murl += p
# print(murl)
ms = murl.split('&') # 分割拼接出来的链接,取得包含音频链接的的列表
# print(ms)
# print(1222)
return ms
def get_list(url):
res = get_url(url)
list999 = etree.HTML(res) # 转换xpath
name = list999.xpath('//div[@class="tit"]/h1/text()') # 书名
lists = list999.xpath('//*[@id="vlink_1"]/ul/li/a/@href') # 所有章节链接
count = int(list999.xpath('count(//*[@id="vlink_1"]/ul/li)')) # 章节数量
path = 'D:/' + name[0].strip() + '/'
print(path)
if not os.path.exists(path):
os.makedirs(path)
i = 1
for list in lists:
surl = 'http://www.ting56.com' + list #拼接url
conlist = get_con(surl)
conurl = get_con(surl)
suffix = conurl[0][-4:] #取后缀名
res = requests.get(conurl[0]).content
print(f'正在下载【{name[0].strip()}】的第{i}/{count}章,当前音频所在url:{surl}')
with open(path + str(i) + suffix, 'wb+') as f:
f.write(res)
i += 1
# url = input('输入56听书网图书目录网址:')
# url = input('输入图书所在链接')
url = 'http://www.ting56.com/mp3/21163.html'
get_list(url)
多线程爬取代码:
# coding:utf-8
# __auth__ = "maiz"
# __date__ = "2020/12/19 17:26"
import os
import re
import threading
import time
import requests
from lxml import etree
def get_url(url): #获取源码
headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)'}
res = requests.get(url , headers=headers)
res.encoding = res.apparent_encoding
if res.status_code == 404:
print('获取源码失败,退出程序')
os._exit(0)
else:
return res.text
def get_con(url):
xml = get_url(url)
ssrl = re.search('var datas=\S*', xml)[0].split('*') #正则获取加密链接数组并且按照*号分割
murl = ''
for i in range(1,int(len(ssrl)) - 1): #遍历获取的数字并转换成 Unicode 值然后拼接!
s = ssrl[i]
p = chr(int(s))
murl += p
ms = murl.split('&') #分割拼接出来的链接,取得包含音频链接的的列表
return ms[0]
def get_list(url):
res = get_url(url)
xml = etree.HTML(res) #转换xpath
name = xml.xpath('//div[@class="tit"]/h1/text()') #书名
lists = xml.xpath('//*[@id="vlink_1"]/ul/li/a/@href') #所有章节链接
count = int(xml.xpath('count(//*[@id="vlink_1"]/ul/li)')) #章节数量
path = 'D:/' + name[0].strip() + '/'
if not os.path.exists(path):
os.makedirs(path)
print(f'开始下载下载【{name[0].strip()}】,本书一共{count}章,请稍等……')
return lists , path
def download_url(list , path , i ,sem):
surl = 'http://www.ting56.com' + list #拼接url
conurl = get_con(surl)
suffix = conurl[-4:] #取后缀名
res = requests.get(conurl).content
print(f'正在下载的第{i} ,当前音频所在url:【{surl}】')
with open(path + str(i) + suffix, 'wb+') as f:
f.write(res)
sem.release() #释放线程
def threads(lists, i = 0 , ths = [] ):
erro = []
path = lists[1]
sem = threading.Semaphore(60) #最大线程数量
for list in lists[0]:
sem.acquire() #取线程,可用线程数减1
i += 1
try:
th = threading.Thread(target=download_url , args=(list , path, i , sem)) #把链接,存储路径、章节名称、线程数量传入
th.start()
ths.append(th)
time.sleep(0.2) #缓一会儿,貌似服务器支撑不了太多的链接!一会儿强迫关闭,一会儿超时!
except :
p = '第' + str(i) + '章下载失败,链接:' + str(list) + '【等待所有进程结束后输出】'
print(f'第{i}章下载失败,链接:{list}')
print('等待所有线程结束后重试!')
erro.append(list)
for t in ths:
t.join()
if erro is not None:
print('下载完毕,下面是下载失败的链接!请自行查看下载')
for el in erro:
print(el)
else:
print('已经全部下载完毕!')
def main(url):
if len(url) == 0:
print('输入网址错误!')
elif 'www.ting56.com' not in url.split('/'):
print('网址错误!')
else:
lists = get_list(url) #获取所有的详情页链接
threads(lists) #开始多线程下载
if __name__ == '__main__' :
# url = input('输入图书所在链接')
url = 'http://www.ting56.com/mp3/21163.html'
main(url)
不管怎么说,每个人的学习方式不同,只要自己喜欢,那就是最好的。以上就是今天给大家分享的爬取56听书网的爬虫代码。右击运行,输入自己喜欢的作品的链接,就可下载成功。