网页音频抓取(异步内部数组导致歌曲无法操作处理异步问题(图))
优采云 发布时间: 2021-10-19 11:12网页音频抓取(异步内部数组导致歌曲无法操作处理异步问题(图))
大致步骤:
目标效果
四、 根据输入值抓取搜索结果数据(一),抓取数据
在QQ音乐手机端网页中,输入数值,仔细搜索数据即可获得
但是双击进入,你会发现浏览器并没有打开对应的json,而是下面的数据
也就是说,我们需要进行跨域的数据请求
找到对应URL跨域所需的数据,并hash数据
↓ 构建-->webpack.dev
跨域请求url
//搜索结果数据
before(app) {
app.get('/api/getSearch', (req, res) => {
var url = 'https://c.y.qq.com/soso/fcgi-bin/search_for_qq_cp'
axios.get(url, {
headers: {
referer: 'https://y.qq.com/m/index.html',
host: 'c.y.qq.com'
},
params: req.query // 通过req从浏览器端发过来的一堆参数(platform,sin,ein等)透传给qq的服务端
}).then((response)=>{ // qq服务端的响应数据,再通过res将响应数据输出到浏览器端
res.json(response.data)
}).catch((error)=>{
console.log(error)
})
})
}
↓ api-->search.js
//搜索结果数据
export function getSearch(query,page,zhida,perpage){
//通过自身模拟服务器访问有host权限的数据
const urlfront = '/api/getSearch'
//把hash做成对象,es6创建对象并赋值,
//固定的hash写在变量js模块里, config.js
const thehash = Object.assign({},commonParams,{
w: query, //关键词
p: page, //展示页数
perpage: perpage, //一页展示多少数据
n: perpage,
catZhida: zhida ? 1 : 0, //是否单独展示歌手
notice: 0,
platform: 'h5',
needNewCode: 1,
zhidaqu: 1,
t: 0,
flag: 1,
ie: 'utf-8',
sem: 1,
aggr: 0,
remoteplace: 'txt.mqq.all',
format: 'json',
})
//执行jsonp模块
return axios.get(urlfront,{
params:thehash
}).then((res)=>{
return Promise.resolve(res.data)
})
}
↓ 搜索Suggest.vue
const perpage = 20 //抓取数据一页有多少数据
props:{
query:{ //父组件*敏*感*词*到的输入框的值,传入来抓取数据
type:String,
default:''
}
},
data(){
return {
page:1,
showSinger:true,
}
}
/**获取数据方法*****/
_getSearch(){
getSearch(this.query,this.page,this.showSinger,perpage).then((res)=>{
if(res.code === ERR_OK){
console.log(res.date)
}
})
},
先输出查看得到的数据,发现数据结构不是我们想要的
res.data中有songs数组和singer对象,我们需要从songs数组中提取我们想要的数据,将singer放入数组中
(二), 提取数据
↓ 搜索Suggest.vue
介绍将歌曲数据歌曲组合成新对象CresteSong.js的方法,见上期文章
import {createSong} from '@/common/js/song.js' //提取数据的方法做成新对象
//歌曲列表数据的提取
_nomalizeSongs(list){
let ret = []
list.forEach((musicData)=>{
if(musicData.songid && musicData.albummid){
//获取歌曲源url数据
let songUrl = ''
getSongs(musicData.songmid).then((res)=>{
if(res.code === ERR_OK){
songUrl = res.req_0.data.midurlinfo[0].purl
ret.push(createSong(musicData,songUrl))
}
})
}
})
return ret
}
↓ 搜索Suggest.vue
将歌手合并为歌曲
//有zhida就合并对象到数组中
_genResult(data,newValue){
let ret = []
//push歌手进空数组
if(data.singerid){
ret.push({...this.zhida,...{type:TYPE_SINGER}}) //es6语法,对象拓展符。等同于object.assign()新建对象
}
//合并歌曲进数组
if (newValue) {
ret = ret.concat(value)
}
return ret
},
这里我们发现输出结果并没有合并到数据中,只有singer和type是数组中的两项。
调试
发现歌曲数组控制台显示如上,正常数组输出为(20)[],上图中的数组输出为空数组,虽然点击可以看到数据,我们可以看到蓝*敏*感*词*标显示:
下面的值是刚刚评估的
点击打开这个对象的时候看到的值不是console.log执行的时候
也就是说,执行时结果为空,长度为0。
打开并放大控制台后,浏览器会出现评估当前变量的值。
虽然这个值的内容为真,但你不可能在不合适的位置调用它的内容,因为当程序运行到你调用它的位置时,序列执行并没有发现该值的存在。
所以我猜测数组为空并且确实存在的原因是我的歌曲数组数据是异步获取的,但是视频教程也是异步的,所以我是异步获取歌曲源url的,内部是异步的。
(三),处理异步导致歌曲数组无法操作
异步问题的处理一般通过使用*敏*感*词*器来完成,例如计算属性和观察器。
这里我们使用*敏*感*词*器来操作
将歌手对象保存为数据,将歌曲数据获取保存为数据,新建歌曲数据获取标志,根据歌曲数据获取完成执行合并
this.zhida = res.data.zhida
this.searchSongs = this._nomalizeSongs(res.data.song.list)
_nomalizeSongs(list){
let ret = []
let pushIndex =0 //判断是否是最最后一次push
list.forEach((musicData)=>{
if(musicData.songid && musicData.albummid){
//获取歌曲源url数据
let songUrl = ''
getSongs(musicData.songmid).then((res)=>{
if(res.code === ERR_OK){
songUrl = res.req_0.data.midurlinfo[0].purl
ret.push(createSong(musicData,songUrl))
/**********把歌曲源数据push后判断是否异步完成************/
pushIndex++
this.pushOver = list.length===pushIndex
}
})
}
})
watch:{
//*敏*感*词*异步问题,对数据无法操作,把值赋值出来
searchSongs(newValue){
console.log(this.pushOver)
//判断异步完成后去合并已存在的数组和singer
if(this.pushOver){
this._genResult(this.zhida,newValue)
}
}
},
//有zhida就合并对象到数组中
_genResult(data,newValue){
let ret = []
//push歌手进空数组
if(data.singerid){
ret.push({...this.zhida,...{type:TYPE_SINGER}}) //es6语法,对象拓展符。等同于object.assign()新建对象
}
//合并歌曲进数组
if (newValue) {
ret = ret.concat(value)
}
this.result = ret
},
另外type push into 数组是在渲染dom的时候用来判断的,区分singer和song li的风格
最终得到一个收录21项(20首歌曲,1位歌手)的数组