1.一般的python爬虫很简单,直接请求对应网址,解析返回的数据即可,但是有很多网站的数据的js动态渲染的,你直接请求是得不到对应的数据的

  这时就需要其它手段来处理了。

2.以一个例子来说明,整个过程,爬取一个音乐网站的对应歌手的歌曲。

  1. 目标网址http://tool.liumingye.cn/music/?page=searchPage,在搜索框输入歌手名字即可得到歌曲。
  2. 如果我们直接请求这个网址:http://tool.liumingye.cn/music/?page=audioPage&type=migu&name=周杰伦,返回的数据不是我们想要的
  3. 在inspect里分析js或xhr数据找到真正的网址,可以看到在NetWork下的XHR中找到我们想要的网址,还有POSt请求时发送的数据

  4. 我们仿照他发起一个post请求,返回的数据确实是我们想要的,里面包含歌曲名字,还有下载地址,歌词等信息,直接请求歌曲下载地址即可。

    import requests
    headers = {
    'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'}
    data={'data':'3c7frUZZlQooe5YYDmZVHi9O4qOxgj8oXuivPGr2sfTT65IGXo85FOqjwtoJPmO-t6ew_q_59dY1SSl7','v':'2'}
    r=requests.post('https://app.onenine.cc/m/api/search',headers=headers,data=data)

    data=r.json()#转为json
    print(data['data']['list'])

  5. 大家不要觉得这样就可以了喔,其实问题还有很多。第一,你要构造POST请求必须要得到data参数的数据,就是那一长串字符串,如果没有data的话,会返回状态码403,禁止访问
  6. 而且每一个歌手或歌曲的data参数都是动态生成的,没有规律的,这样的话,你每构造一个POST请求就要在游览器那里看一下data参数是多少,根本不符合爬虫的要求。
  7. 第二,返回的数据只有二十首歌曲,想要得到更多,就必须点击‘下一页'按钮,网站才会去请求下一个二十首,然后渲染到网页上,所以就算有data参数,也无法爬到更多数据。

3.这时就到了Seleninum和Browsermob-proxy出场了。Seleninum是一个用于测试网站的自动化测试工具,支持各种浏览器包括Chrome、Firefox、Safari等主流界面浏览器,同时也支持phantomJS无界面浏览器。它主要得功能就是可以模拟游览器行为,包括执行js代码,寻找各种元素,发送点击,滑动事件等等。这样我们就可以实现点击功能了。selenium的教程推荐这个,他写得不错,比我写得好

https://blog.csdn.net/qq_32502511/article/details/101536325

Browsermob-proxy是一个开源的Java编写的基于LittleProxy的代理服务。Browsermob-Proxy的具体流程有点类似与Flidder或Charles。即开启一个端口并作为一个标准代理存在,当HTTP客户端(浏览器等)设置了这个代理,则可以抓取所有的请求细节并获取返回内容.简单来说就是它可以将网站的请求和返回的数据获取到,就如游览器的'inspect'功能,这样我们就可以获取到‘seacher’的数据了

Browsermob-proxy的教程推荐这个,不难的,看一下就可以上手了。https://blog.csdn.net/qq_32502511/article/details/101536325

4.我们分析一下获取到的数据,包含名字和歌词,封面,下载地址。歌曲的下载地址有四种,url_m4a是流畅,128是标准,320是高品,flac则是无损音乐。url那一栏是在线播放

4.有上面这些准备后就可以写代码爬取数据了,代码如下(有详细注释)

from selenium import webdriver
import time
import os
import threading
import simplejson as json
from browsermobproxy import Server
import requests
from selenium.webdriver.chrome.options import Options #Browsermob-proxy的路径
server=Server(r"D:\Python3.7\browser-proxy.bat\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat")
server.start()#启动browsermob-proxy
proxy=server.create_proxy()
chrome_options=Options() #获取游览器对象,设置无界面模式
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
chrome_options.add_argument('--headless')#无头模式,不开启游览器界面
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--incognito')
driver=webdriver.Chrome(chrome_options=chrome_options)#启用谷歌游览器 #获取音乐的信息
def getDownloadUrls(name): musicUrl='http://tool.liumingye.cn/music/?page=audioPage&type=migu&name='+str(name)
proxy.new_har('music',options={'captureHeaders':True,'captureContent':True})
driver.get(musicUrl)#请求网站
time.sleep(3)#等待页面加载完成,必须要延时,不然获取不到数据
lists=[]
#获取3页数据一共60首歌
for i in range(3):
index=0
result=proxy.har#获取所有请求网址
for entry in result['log']['entries']:
url=entry['request']['url']
#找对应的网址,我们要的是,search网址的
if "app.onenine.cc/m/api/search" in url:
index+=1
'''
因为每点击下一页都会产生一个新的‘search',
而proxy每次都会把所有的请求获取到,所以上一个的’search‘也会获取到
所以要判断排除掉,只获取最新的’search'
'''
if index>i:
content = entry['response']['content']
text=content['text']
data=json.loads(text)['data']
lists.extend(data['list']) #这里就是获取到的json数据.每一次添加20首歌曲的信息进去 #滑到底部
js="window.scrollTo(0,10000)"#滑动滚动条的js代码,如果元素不在页面上显示,是找不到的,所以滑动,让下一页的按钮显示出来
driver.execute_script(js)#执行·js代码
#点击下一页,获取更多歌曲
nextBtn=driver.find_element_by_css_selector('#player>div.aplayer-more')#找到下一页的按钮
nextBtn.click()#发送点击事件
time.sleep(1)#延时1秒等待数据加载
return lists #用于下载音乐代码
def download(path,musicName,folder,ext): r=requests.get(path)
f=open(folder+'/'+musicName+ext,'wb')
f.write(r.content)
f.close() #在lists例表中提取音乐的下载地址和歌曲名字
def downloadMusic(name,type,lists):
'''
name:歌手名字,为每一个歌手都新建一个文件夹
type:表示要下载何种音质
lists:获取的音乐数据列表
'''
isExists=os.path.exists(name)
if not isExists:
os.makedirs(name)
musicName=''
path=''
ext=''
for item in lists:
for key,value in item.items():
ext='.mp3'
key=str(key)
if key=='name':
musicName=value
elif key=='artist':
musicName=musicName+'-'+value
elif key=='url_m4a' and type==0:#m4a表示流畅
path=value
elif key=='url_128' and type==1:#128是标准
path=value
elif key=='url_320' and type==2:#320是高品质
path=value
elif key=='url_flac'and type==3:#flac表示无损
path=value
ext='.flac' if len(path)!=0:
#每一首歌开启一个线程去下载
t = threading.Thread(target=download,args=(path,musicName,name,ext))
t.start()
t.join()
path=''
musicName='' if __name__=='__main__': signer=input("输入歌手名字:")
lists=getDownloadUrls(signer)
print('获取完成,开始下载音乐')
downloadMusic(signer,0,lists)#0表示下载流畅音质的
print('下载结束')

等待一段时间就爬取成功了。

5.这个网站上还有歌单和各种音乐榜单,我们一样可以爬取下来,原理都一样,我就不多解释了。你只要掌握上面的东西,爬取这些东西,还是很简单的,只要给点耐心去学一下。

  附上完整代码,包括爬取歌单和榜单

from selenium import webdriver
import time
import os
import threading
import simplejson as json
from browsermobproxy import Server
import requests
from selenium.webdriver.chrome.options import Options #Browsermob-proxy的路径
server=Server(r"D:\Python3.7\browser-proxy.bat\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat")
server.start()#启动browsermob-proxy
proxy=server.create_proxy()
chrome_options=Options() #获取游览器对象,设置无界面模式
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
chrome_options.add_argument('--headless')#无头模式,不开启游览器界面
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--incognito')
driver=webdriver.Chrome(chrome_options=chrome_options)#启用谷歌游览器 #获取音乐的信息
def getDownloadUrls(name): musicUrl='http://tool.liumingye.cn/music/?page=audioPage&type=migu&name='+str(name)
proxy.new_har('music',options={'captureHeaders':True,'captureContent':True})
driver.get(musicUrl)#请求网站
time.sleep(3)#等待页面加载完成,必须要延时,不然获取不到数据
lists=[]
#获取3页数据一共60首歌
for i in range(3):
index=0
result=proxy.har#获取所有请求网址
for entry in result['log']['entries']:
url=entry['request']['url']
#找对应的网址,我们要的是,search网址的
if "app.onenine.cc/m/api/search" in url:
index+=1
'''
因为每点击下一页都会产生一个新的‘search',
而proxy每次都会把所有的请求获取到,所以上一个的’search‘也会获取到
所以要判断排除掉,只获取最新的’search'
'''
if index>i:
content = entry['response']['content']
text=content['text']
data=json.loads(text)['data']
lists.extend(data['list']) #这里就是获取到的json数据.每一次添加20首歌曲的信息进去 #滑到底部
js="window.scrollTo(0,10000)"#滑动滚动条的js代码,如果元素不在页面上显示,是找不到的,所以滑动,让下一页的按钮显示出来
driver.execute_script(js)#执行·js代码
#点击下一页,获取更多歌曲
nextBtn=driver.find_element_by_css_selector('#player>div.aplayer-more')#找到下一页的按钮
nextBtn.click()#发送点击事件
time.sleep(1)#延时1秒等待数据加载
return lists #用于下载音乐代码
def download(path,musicName,folder,ext): r=requests.get(path)
f=open(folder+'/'+musicName+ext,'wb')
f.write(r.content)
f.close() #在lists例表中提取音乐的下载地址和歌曲名字
def downloadMusic(name,type,lists):
'''
name:歌手名字,为每一个歌手都新建一个文件夹
type:表示要下载何种音质
lists:获取的音乐数据列表
'''
isExists=os.path.exists(name)
if not isExists:
os.makedirs(name)
musicName=''
path=''
ext=''
for item in lists:
for key,value in item.items():
ext='.mp3'
key=str(key)
if key=='name':
musicName=value
elif key=='artist':
musicName=musicName+'-'+value
elif key=='url_m4a' and type==0:#m4a表示流畅
path=value
elif key=='url_128' and type==1:#128是标准
path=value
elif key=='url_320' and type==2:#320是高品质
path=value
elif key=='url_flac'and type==3:#flac表示无损
path=value
ext='.flac' if len(path)!=0:
#每一首歌开启一个线程去下载
t = threading.Thread(target=download,args=(path,musicName,name,ext))
t.start()
t.join()
path=''
musicName='' #获取歌单的id和歌单名字
def getSongsSheetId(type): id=[]
sheetNames=[]
#这里的 limit表示获取多少个歌单,2表示两个
url='https://musicapi.leanapp.cn/top/playlist?limit=2&offset=0&order=hot&cat='+str(type)
r=requests.get(url);
data=r.json()
playlist=data['playlists']
for item in playlist:
id.append(item['id'])
sheetNames.append(item['name'])
print(id) return id,sheetNames
#下载歌单的歌曲
def getSongsSheetSongs(type): id,sheetNames=getSongsSheetId('日语')#这里可以做成变量,比如华语,欧美,流行....
url='http://tool.liumingye.cn/music/?page=audioPage&type=YQD&name=https%3A%2F%2Fmusic.163.com%2F%23%2Fplaylist%3Fid%3D'
lists=[]
for i in range(len(id)):
reqUrl=url+str(id[i])
proxy.new_har('lists',options={'captureHeaders':True,'captureContent':True})
driver.get(reqUrl)
time.sleep(3)
result=proxy.har
for entry in result['log']['entries']:
repUrl=entry['request']['url']
if "app.onenine.cc/m/api/search" in repUrl:
content = entry['response']['content']
text=content['text']
data=json.loads(text)['data']
lists=data['list'][:]
downloadMusic(sheetNames[i],type,lists) #榜单,榜单比较少所以可以,直接复制data数据然后直接请求
def getMusicListSongs(listType,quality):
'''
listType:何种榜单
quality:何种音质
'''
musicLists={'飙升榜':'9a96BCVWtsdySz5JAlEM4ETawT0kPc0PKnwYwhGTCdL_ABeeIChrZMDWVoEkAy8xVORmVw_mS9xE1maSBbzV1ISsUCDTq2_sWMDY2T-KnB7cqYjoRo9EYTROqsURCA',
'新歌榜':'0eb8XS226D93TYlB6f0YRLwpd88EElQZglIn4CnZo9CUa8yqKtPDCG-pL3GKi_9UoBxJClL04dhhdgjAh-EAho2EkPBct2PF2tJl3F8p2atv3IwIxgPYE9iDGFKD',
'原创':'9cecTgCD-VsNzA2od9fsyX6c2KpOCdI1VfGRMO26vy4XgwyApkwNtsii9u2La2FS1xoBsJL-nPFpORJ1t9Vd3T0aSzg-0R2LWbS8Yj8wJeYsTVlnnbzFdMeO88OV',
'热歌榜':'bfaFw92RlNQ6e3pJQ9tIkNtitPFqTUbXZHDzE8yuiJ-nNo7gpsDldd5R6AQ83eqQCuE9Id2GiS6ycC9Q8wqeB-HNfxC-Q-Mbv-Amdir7AHal8MKsHnZYeiCWKGG',
'ACG音乐榜':'b91b2EKQBotaf_vdDg3ttFZwGBGJ_uFpbSf8oSjga2p7NKAsNCCHFdj_dywOpfalhPUQz78HAwDNqp127vWDFCP5Ie4pKJEbigRXjr0FwVgPcrhyR5A_RvbJibnGlw',
'欧美热歌榜':'10e2UIqDLgcQvg74T9Y6BU0mlxUHvstcHkV5UKHPkSDzyi3TRBORkKAKLtAspirLXvbbTwN4B8Jm_IYzis6kbq1VkFnbcpM28AV54vdGk9Trj1ycEP1FbclVuvxGAXuX',
'抖音热歌榜':'b0758Dllkk2pO4ripW44AWtSVQMHsmPgxNcVsJZmQKtNgoIi4dCd0CVRsKOIt69f6TFRffmQhJKCp6dBO9l1UGyiwUks3T5xlxHndE5oOz0NJogMrE49W6e2S8xc-sZb',
'古典音乐榜':'c6540n5sOF11X1eYySdN9elyUeEtSPKAzU0b-Pm41g5Kpt7WGD7E6pEVyNNMEsMb5OL5f5NC-bAt6Prqvesz9xIwYWDrHCbfAsWldzvzMDJCNybErloRvh98iev2oQ'
}
lists=[]
url='https://app.onenine.cc/m/api/search'
headers={'content-type':'application/x-www-form-urlencoded; charset=UTF-8','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'}
data={'data':'b91b2EKQBotaf_vdDg3ttFZwGBGJ_uFpbSf8oSjga2p7NKAsNCCHFdj_dywOpfalhPUQz78HAwDNqp127vWDFCP5Ie4pKJEbigRXjr0FwVgPcrhyR5A_RvbJibnGlw','v':'2'}
r=requests.post(url,headers=headers,data=data)#构造post请求
data=r.json()
print(len(data))
lists=data['data']['list'] #data=data['list'] #print(data)
downloadMusic(listType,quality,lists) if __name__=='__main__': signer=input("输入歌手名字:")
lists=getDownloadUrls(signer)
print('获取完成,开始下载音乐')
downloadMusic(signer,0,lists)#0表示下载流畅音质的
print('下载结束')
'''
#这个是下载歌单的
getSongsSheetSongs(0)
'''
'''
#这个是下载榜单的
getMusicListSongs('ACG音乐榜',1)
'''
# getSongsSheetSongs(1)
# getMusicListSongs('ACG音乐榜',1)
# print('end')
server.stop()
driver.quit()

效果

6.在Windows下安装Browsermob-proxy,可能比较麻烦一点,如果不会,可以找。

有其他问题也可以随时留言。

【音乐爬虫】Python爬虫-selenium+browsermob-proxy 解决动态网页 js渲染问题的更多相关文章

  1. Python:利用 selenium 库抓取动态网页示例

    前言 在抓取常规的静态网页时,我们直接请求对应的 url 就可以获取到完整的 HTML 页面,但是对于动态页面,网页显示的内容往往是通过 ajax 动态去生成的,所以如果是用 urllib.reque ...

  2. scrapy和selenium结合抓取动态网页

    1.安装python (我用的是2.7版本的) 2.安装scrapy:   详情请参考 http://blog.csdn.net/wukaibo1986/article/details/8167590 ...

  3. [爬虫]Python爬虫基础

    一.什么是爬虫,爬虫能做什么 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来.比如它在抓取一个网 ...

  4. 爬虫-Python爬虫常用库

    一.常用库 1.requests 做请求的时候用到. requests.get("url") 2.selenium 自动化会用到. 3.lxml 4.beautifulsoup 5 ...

  5. 【python】Selenium隐藏控制台解决办法

    一.起因: 使用selenium 驱动浏览器的时候,如果使用headless模式,会有dos窗口弹出,输出监听信息,有时不想看到,很是麻烦. 二.解决办法: 修改源码:Lib \ site-packa ...

  6. [爬虫]Python爬虫进阶

    请跳转到以下页面查看: 爬虫进阶

  7. python爬虫之selenium、phantomJs

    图片懒加载技术 什么是图片懒加载技术 图片懒加载是一种网页优化技术.图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时 ...

  8. Python爬虫教程

    Python爬虫(1):基本原理 Python爬虫(2):Requests的基本用法 Python爬虫(3):Requests的高级用法 Python爬虫(4):Beautiful Soup的常用方法 ...

  9. Python爬虫的简单入门(一)

    Python爬虫的简单入门(一) 简介 这一系列教学是基于Python的爬虫教学在此之前请确保你的电脑已经成功安装了Python(本教程使用的是Python3).爬虫想要学的精通是有点难度的,尤其是遇 ...

随机推荐

  1. Typescript | Vue3源码系列

    TypeScript 是开源的,TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript.编译出来的 JavaScript 可以运行在任何浏览器上.TypeS ...

  2. java返回树形结构的正确姿势

    业务场景 通常我们前端需要一个树形的导航菜单或者分类菜单,如后台权限管理中的权限树,亦或者下面例子中商城系统的商品分类多级菜单(一般为三级菜单) 数据库设计 数据库设计,采用parentId来指向自己 ...

  3. AOP理论

    目录 AOP理论 什么是AOP 那Spring AOP,AspectJ又是啥呢? 为什么说AOP是OOP的补充和完善呢? 应用场景举例 AOP的优点 AOP的术语整理 AOP理论 什么是AOP AOP ...

  4. 如何利用 docker 快速部署 Mysql 服务

    docker 基础教程不再多说,这里只着重讲如何使用 docker 部署 mysql 服务 docker 拉取 访问 dockerhub,搜索关键词 mysql,我这里选择 mysql-server, ...

  5. 官网安装Python包太慢?教你三种下载安装方式-PiP、conda、轮子,教你三种Pytorch的下载安装方式,保证你再也不用出现Error

    上一期我们介绍了CUDA下载安装以及其总结,这一期教大家如何在Anaconda中使用CUDA来进行加速.神经网络依赖cuDNN的下载安装,以及下载和安装Pytorch-GPU安装包的三种方式(cond ...

  6. nodeJS 下载与安装,环境配置

    1.什么是nodeJs: 简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. Node.js是一 ...

  7. 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码

    VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...

  8. PHP的八个魔术常量

    1. 什么魔术常量 预定义常量:预定义常量就是PHP内置的常量,预先定义好的 PHP有很多预定义常量,比如:PHP_VERSION(版本号).PHP_OS(操作系统). 这些普通的预定义常量在程序中的 ...

  9. 反序列化之PHP

    反序列化漏洞 #PHP反序列化 原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果.在反序列化的过程中自动触发了某些魔术方法. ...

  10. tcp、http 学习小结

    tcp.http 学习小结 前言 最近因为cdn的一个问题,困扰了自己好久.因为需要统计网站访问的成功数,而且要求比较精确.目前的实现不能满足要求,因为没有区别访问成功与否,也没有对超时做处理.期间解 ...