Nuxt.js 是一个基于 Vue.js
的服务端渲染(SSR)框架,它可以帮助开发者更高效地构建高性能、可搜索引擎优化的前端应用。相较于传统的单页面应用(SPA),Nuxt.js
生成的 HTML 文件更具利于搜索引擎优化,并加快了首屏加载时间。
但是道理我都懂,那么如何去爬取它渲染的页面数据呢。
已知有三种数据:
- 静态渲染数据: 就是直接请求写在HTML源码文件的数据,这部分我们可以用XML解析器去直接解析抓取。
- 异步渲染数据:通过 Network 控制台查看请求抓取即可。
- 动态渲染数据:这部分的数据储存在一个
<script id="__NUXT_DATA__" />
标签里面,我们依照上面的方法,读取<script id="__NUXT_DATA__" />
的内容可以发现,这是一个无序数组。根据观察可以发现,他的结构为Array<{ [key]: valueIndex extends number } | value extends any>
。那么方法就显而易见了。我们写一个支持任意层级的对象挖掘函数digObject<T>(object: Array | Object, matchFunction: (obj: any) =>boolean[, cache: Array<T>]): Array<T>
来对无序数组进行挖掘。
我们着重讲一下动态渲染数据
的数据获取方式,我们以 这样一个页面 为例子来实验一下:
如图,这个网页是一个标准的用NUXT渲染的页面,其中红框部分就用到了动态渲染,而我们需要获取的是绿色部分的列表。我们先看略看一下NUXT_DATA
的内容:
const s = document.getElementById('__NUXT_DATA__');
const data = JSON.parse(s.innerHTML);
console.log(data);
我们就发现了这样的一个数据结构:
仔细对比一下就会发现这就是我们要的对象,那我们根据数据特征: 含有key为 SID的对象去挖掘,就可以找到我们想要的东西了。
那我们很简单就写出了一下代码:
const s = document.getElementById('__NUXT_DATA__')
const data = JSON.parse(s.innerHTML)
const digObject = (ob, matchCall, cache = [])=>{
if (matchCall(ob)) return cache.push(ob),cache;
if (typeof ob != 'object') return cache;
if (!ob) return cache;
Array.isArray(ob) ? ob.map(v=>{
if(matchCall(v)) return cache.push(v);
if(typeof v === 'object') digObject(v, matchCall, cache);
}) : digObject(Object.values(ob), matchCall, cache);
return cache;
};
// 查找拥有 SID 为键名的对象。
const call = v => v && Object.keys(v).length> 0 && Object.keys(v).some(k=>['SID'].indexOf(k)>-1);
const res = digObject(data, call)
// 把对象的 valueIndex 换成 value
res.map(v=> Object.entries(v).map(kv=>v[kv[0]]=data[kv[1]]))
console.log("res:", res);
看,很简单不是吗 ^ w ^ !