python爬取喜马拉雅vip⾳频_Python简易爬⾍教程(三)--
爬取喜马拉雅⾳频
上⼀篇我们重点介绍了如何把爬取到的图⽚下载下来。没错,如果你还记得的话,我们使⽤的是urlretrieve这个Python⾃带的下载模块。所以,到现在,爬⾍框架的三个基本组成:获取⽹页,寻信息,收集信息,我们已经学习完成。相信⼤家现在已经可以独⽴地编写⾃⼰的爬⾍,爬取⾃⼰感兴趣的⽹站了。
然⽽,随着不断实践,我们会发现,不是所有⽹站都是像我们前⾯爬取的搜狐新闻和新浪图⽚那样简单的。⼤部分⽹站,尤其是内容⽹站,会对⾃⼰的数据进⾏保护,采取⼀些反爬⾍的措施。最常见的,分以下这⼏种。
第⼀种,最简单的呢,是⼀些⽹站需要登陆才能访问特定资源。⽐如微博,知乎,tumblr等等。它需要确定我们的⽤户⾝份,才能允许读取我们的数据列表,⽐如粉丝,关注话题,收藏等等。那么遇到这种情况呢,我们只需要让我们的爬⾍模拟浏览器登陆就可以了。哈哈,⼤家不要忘记啦,这依然属于爬⾍的第⼀个步骤,即,先登陆,再获取⽹页源代码。所以,我们依然可以使⽤requests这个库进⾏模拟登陆,获取代码的操作。这个⽐较简单,⽹上随便都可以搜索到两⾏代码,本节就不再赘述了。
那么第⼆种,最直接的,也是最有效的。隐藏资源的链接。如图所⽰,这⾥的href是⼀个javascript,在⽹页源码⾥不明⽰。
image
这种情况,需要浏览器监测到我们点击了这个链接,触发这个JavaScript,才会向⽹站发出⼀个请求,⽹站才会反馈给浏览器⼀个真正的href地址。那么,我们在爬取这⼀类⽹页的时候,就要⾯临⼀个如何模拟浏览器发出点击请求的问题。这⼀类的⽹站很多,典型的特点就是,链接必须单击打开,如果右键在新标签页打开,就会跳转到about:blank空标签页。相信⼤家⼜有这样的经历。
image
这种⽹站,处理的重点在于,弄清楚浏览器发出的请求是什么,⽹站返回的⼜是什么。然后我们才能模拟。所以,这⼀篇教程主要介绍,当我们遇到这种⽹页的时候,该怎么处理,这样⼤家能够爬取的⽹站就会更多了。
我们以爬取喜马拉雅⽹站上的免费⾳频为例。
打开专辑的页⾯。
image
我们尝试使⽤requests的get,发现出现错误,⽆法获得⽹页源代码。这就属于上⾯说的第⼀种类型,⽹站识别到我们是爬⾍,阻⽌我们获取代码。因此,我们使⽤requests.session, 把⾃⼰伪装成浏览器。
page = 'www.ximalaya/qinggan/209378/' #专辑地址
session = requests.session()#使⽤session⽅法
r = (page, headers=headers)
#这个headers就是包含浏览器特征的⼀些数据,为了将我们伪装成浏览器。
headers = {
"User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/72.0.3626.109 Safari/537.36',
'host': 'www.ximalaya',
'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8', 'Accept-Encoding': 'gzip, deflate, br',
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
'Upgrade-Insecure-Requests': '1',
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'}
这个⾳频的href是, 显然,这不是⼀个完整的url地址。我们结合浏览器的地址栏,将其补上。
soup1 = , 'html.parser')
audios = soup1.find_all(class_='text _OO')
print(audios)
for audio in audios:
audio_name = audio.a['title']
audio_url = 'www.ximalaya' + audio.a['href']
audio_id = re.sub('/qinggan/209378/', '', audio.a['href'])
好了,现在我们跳转到这条⾳频的页⾯去。
image
这下我们发现,我们不到这个⾳频的地址在哪⾥。这个播放按钮只是对应⼀个空的标签 i,⾥⾯没有href,底下对应⼀个JavaScript。
image
这就是我们这节需要解决的情况了。我们将检查⼯具切换到network这个标签下的XHR⼦标签,看看当我们点击这个播放按钮,触发这个JavaScript之后,会发⽣什么,浏览器会发出什么请求,我们⼜会收到什么反馈。 这是获得⾳频地址的重点了。
image
image
image
原来如此啊。喜马拉雅把⾳频的id,名称,地址全部放在这个字典⾥了。这样,我们就可以模拟浏览器发送请求了,然后从它返回的这个字典⾥读取信息了。显然,这个url⾥pagenum是指专辑⾳频列表的页⾯,这个字典包含这个页⾯中所有⾳频的信息。那我们就可以根据这个字典把这个专辑这个页⾯的⾳频全部下载下来。
audiodic = (get_audio, headers=headers) #获取这个字典
for i in range(0,30):
try:
src = audiodic.json()['data']['tracksForAudioPlay'][i]['src'] #获取⾳频地址
audio_name= audiodic.json()['data']['tracksForAudioPlay'][i]['trackName'] #获取⾳频名称
except:
print('不能解析')
else:
print(src)
filename = './' + audio_name+'.m4a' #别忘记加上⽂件后缀名
urllib_download(src, filename) #调⽤下载函数下载⾳频并命名
好了,接下来就简单了,相信urlib_download⼤家通过上⼀节的学习已经熟悉了。⼤家可以⾃⾏编写。然后,这个专辑⼀共有三页,我们通过把pagenum改成1,2,3, 就可以将整个专辑都下载下来。
完整代码如下,我还加⼊了多线程⽅法和多进程⽅法,为了使爬⾍加速。这⼀块⼤家感兴趣的话可以了解⼀下。不过,不⽤多线程也没关系,上⾯那部分的代码已经是核⼼了,也可以直接使⽤。
from bs4 import BeautifulSoup
quest import urlopen
import pickle
import re
import random
import requests
from queue import Queue
import ssl
import concurrent.futures
import time
# ssl._create_default_https_context = ssl._create_unverified_context #取消ssl认证s
#定义下载程序
def urllib_download(url, filename):
quest import urlretrieve #这个是下载⽂件的库
import os #这个是⽤于创建⽂件⽬录
if ists(filename) == False: #如果⽂件不存在,创建⽂件
urlretrieve(url, filename)
python 爬虫教学else:
pass
#定义爬⾍
def download(page,headers):
session = requests.session()
r = (page, headers=headers)
audiodic = (get_audio, headers=headers) #获取这个字典
for i in range(0,30):
try:
src = audiodic.json()['data']['tracksForAudioPlay'][i]['src'] #获取⾳频地址
audio_name= audiodic.json()['data']['tracksForAudioPlay'][i]['trackName'] #获取⾳频名称
except:
print('不能解析')
else:
print(src)
filename = './' + audio_name+'.m4a' #别忘记加上⽂件后缀名
urllib_download(src, filename) #调⽤下载函数下载⾳频并命名
#分析页⾯
#
# #定义多线程⽅法
# def multithreading(pages,headers):
#
# import threading
# import time
# threads = []
# thread_star_time = time.time()
# for page in pages:
# t = threading.Thread(target=spider1,args=(page,))#注意这⾥参数后⾯要有个逗号,不然报错
# threads.append(t)
# print(threads)
# for thread in threads:
# thread.start()
# print('线程',thread,'启动')
# thread.join()
# threadtime = '全部下载完成,多线程使⽤' + str(time.time() - thread_star_time) + '秒'
# q.put(threadtime)
#定义 多进程⽅法
def multiprocessing(pages,headers):
import multiprocessing as mp
import time
processes = []
process_star_time = time.time()
for page in pages:
t = mp.Process(target=download,args=(page,headers,))#注意这⾥参数后⾯要有个逗号,不然报错processes.append(t)
print(processes)
for process in processes:
process.start()
print( '进程',process,'启动')
process.join()
processtime = '全部下载完成,多进程使⽤' + str(time.time() - process_star_time) + '秒'
q.put(processtime)
#
if __name__ == "__main__":
# 解析页⾯列表
q=Queue()
for p in range(1,4):
page = 'www.ximalaya/qinggan/209378/p'+p
headers = {
"User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36',
'host': 'www.ximalaya',
'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8', 'Accept-Encoding': 'gzip, deflate, br',
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
'Upgrade-Insecure-Requests': '1',
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'}
global pages
pages = []
pages.append(page1)
pages.append(page2)
pages.append(page3)
print(pages)
# multithreading(pages)
multiprocessing(pages,headers)
# for i in range(1, 3):
())
print('程序结束')
#全部下载完成,多进程使⽤1408.531194448471秒
# 程序结束
好了,到此结束。我们已经成功下载了这张专辑的所有⾳频。
image
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论