需求
周末的时候我在爬一个网站,里面的数据是 table,代码类似于下面的这种。
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
我需要获取上面的数据,并且整理成数组结构,类似这样 [[Jill,Smith,50],[Eve,Jackson,94]]
实现
我用 js 脚本获取到了所有的行数据
let getTr = document.querySelectorAll('tr');
是个数组,都是 tr
也就是行数据,然后每个元素都有 children
属性,代表了 td
,也就是列数据。类似下面这种。
let testData = [
{
title: '1',
children: [],
aaa: '123',
bbb: '345',
},
{
title: '2',
children: [
{
title: '3',
children: [
{
title: '4',
children: [],
aaa: 344,
bbb: 5345,
},
],
},
],
aaa: 123,
bbb: 432,
},
{
title: '5',
children: [],
aaa: 344,
bbb: 5345,
},
];
但是我只需要获取里面的 title
和 aaa
这两个属性的值,其他的都不需要。并且下面的 children
也需要遍历一下,最后拿到的数据就像下面这种。
let getData = [
{
title: '1',
children: [],
aaa: '123',
},
{
title: '2',
children: [
{
title: '3',
children: [
{
title: '4',
children: [],
aaa: 344,
},
],
},
],
aaa: 123,
},
{
title: '5',
children: [],
aaa: 344,
},
];
于是我写了个函数
function deepGetData(data, params) {
let { includeNameList, includeChildrenNameList } = params;
let newArray = [];
for (let index = 0; index < data.length; index++) {
const dataElement = data[index];
let newData = {};
for (let index = 0; index < includeNameList.length; index++) {
const includeName = includeNameList[index];
if (includeName in dataElement) {
newData[includeName] = dataElement[includeName];
}
}
for (let index = 0; index < includeChildrenNameList.length; index++) {
const includeChildrenName = includeChildrenNameList[index];
if (includeChildrenName in dataElement) {
if (dataElement[includeChildrenName].length > 0) {
newData[includeChildrenName] = deepGetData(
dataElement[includeChildrenName],
params
);
}
}
}
newArray.push(newData);
}
return newArray;
}
使用方法
deepGetData(testData, {
includeNameList: ['title'],
includeChildrenNameList: ['children'],
});
改进
我觉得上面函数 deepGetData 应该还可以再优化一下,因为我用的是暴力递归。然后上面的函数方法应该很常见,我不知道应该叫什么名字(怎么命名),所以临时用的 deepGetData,写本文发出来就是为了让大佬们帮忙看看。
后记
我得谦虚一下,我写完之后也没 debug,竟然一下子就跑通了,可能是方法太简单了。