扁平化Node中的JSON API响应



从API响应返回的JSON对象:

{3 items
"total_reviews":574
"stars_stat":{5 items
"1":"2%"
"2":"1%"
"3":"3%"
"4":"8%"
"5":"85%"
}
"result":[10 items
0:{9 items
"id":"R3BWKTLO7CM3Y9"
"asin":{...}2 items
"review_data":"Reviewed in the United States on April 15, 2022"
"date":{2 items
"date":"April 15, 2022"
"unix":1649988000
}
"name":"Sally N."
"rating":5
"title":"Great alcohol !"
"review":"Great products"
"verified_purchase":true
}
1:{...}9 items
2:{...}9 items
3:{...}9 items
4:{...}9 items
5:{...}9 items
6:{...}9 items
7:{...}9 items
8:{...}9 items
9:{...}9 items
]

我尝试了各种方法,但一直卡住实现的方法或意识到它是错误的,所以我只是注释掉了所有的东西,我尝试过。我首先尝试在响应对象中选择特定信息并将其存储在变量中,然后将信息传递给与我需要的CSV头匹配的记录对象,因此我可以将其写入文件,但是,无法使其在循环中迭代地工作以获取我需要的不同键/值对。然后我读了一个内置的json对象函数,它可以让你根据键object.keys,值object.valuesobject.entries来循环json对象,但是我有嵌套的键/值,我需要的一些信息是嵌套的。所以我认为解决方法是找出如何平JSON对象到kv我需要,这就是我寻求帮助。最终尝试将此信息写入csv文件。

我需要以下字段:客户名称,产品名称,SKU,审查内容,星级,时间和日期创建

My Code I've try:

const axios = require("axios");
const converter = require("json-2-csv");
const fs = require("fs");
const moment = require('moment');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
const csvWriter = createCsvWriter({
path: './ProductReviews.csv',
header: ['asin', 'name', 'review', 'rating'].map((item) => ({ id: item, title: item }))
})
const options = {
method: 'GET',
url: 'https://amazon23.p.rapidapi.com/reviews',
params: {asin: 'B00DUGMVC6', sort_by: 'recent', page: '1', country: 'US'},
headers: {
'X-RapidAPI-Key': 'redacted',
'X-RapidAPI-Host': 'redacted'
}
};

axios.request(options).then(function (response) {
console.log(response.data);
// for (let i = 0; i < 10; i++  ) {
// let name = response.data.result[i].name;
// let content = response.data.result[i].review;
// let rating = response.data.result[i].rating;
// let date = response.data.result[i].date.date

// let momentvar = moment(date, 'MMM DD, YYYY').format();

// const records = [
//   {
//     customername: name, productname: 'Isopropyl Alcohol 99.9%', sku: 'B00DUGMVC6', reviewcontent: content, starrating: rating, timeanddate: date
//   }
// ]

// for (let [key, value] of Object.entries(response.data)) {
//   console.log(key, value);
// }    

// try { 
//    csvWriter.writeRecords(response.data.result[0]);
// } catch (error) {
//   console.log(error);
// }

// converter.json2csv(response.data, (err, csv) => {
//     if (err) {
//       throw err;
//     }

//     fs.writeFileSync('todos.csv', csv);
// })

// csvWriter.writeRecords(records)       // returns a promise
//   .then(() => {
//       console.log('...Done');
//   });

// }

// var response = JSON.parse(response);
// console.log(response);

// csvWriter.writeRecords(response.data)

// converter.json2csv(response.data, (err, csv) => {
//     if (err) {
//         throw err;
//     }

//     console.log(csv);
// })

}).catch(function (error) {
console.error(error);
});

只是浏览css-writer文档,看起来包需要两个js对象:一个描述头,另一个记录数组,其键值与头对象中给出的id匹配。

从我对OP的输入对象的理解来看,转换是直接的。唯一不清楚的是应该为asin键写什么,在问题中它被描述为一个对象,但没有进一步阐述。

下面是转换到csv-writer参数的演示。在其中,我们只需要对asin对象进行字符串化…

const data = {
"total_reviews":574,
"stars_stat":{
"1":"2%",
"2":"1%",
"3":"3%",
"4":"8%",
"5":"85%"
},
"result":[
{
"id":"R3BWKTLO7CM3Y9",
"asin":{ 
"original":"B00DUGMVC6",
"variant":"B00DUGMVC6"
}, 
"review_data":"Reviewed in the United States on April 15, 2022",
"date":{
"date":"April 15, 2022",
"unix":1649988000
},
"name":"Sally N.",
"rating":5,
"title":"Great alcohol !",
"review":"Great products",
"verified_purchase":true
},
// more like this
]
}
const result = data.result;
// OP should replace the previous line with const result = response.data.result;

const header = ['asin', 'name', 'review', 'rating'].map((item) => ({ id: item, title: item }))
const records = result.map(({ asin: { original, variant } , name, date: { date }, review, rating }) => {
date = new Date(date).toISOString();
return { original, variant, name, review, rating, date };
});
console.log(header, records);
// // OP should replace the previous line with:
// const csvWriter = createCsvWriter({
//   path: './ProductReviews.csv',
//   header: header
// })
// csvWriter.writeRecords(records)

编辑调用和编写几个页面可能看起来像下面这样。注意:(1)从阅读中,我了解到asin就像一个产品id,可能在所有评论中都是不变的,(2)合理的低音量(看看它是否执行,如果不执行则考虑流式传输),(3)猜测没有记录返回一个页面意味着我们完成了。

async function getReviewPage(asin, page, csvWriter) {
const options = {
method: 'GET',
url: 'https://amazon23.p.rapidapi.com/reviews',
params: {asin, sort_by: 'recent', page: page+'', country: 'US'},
headers: {
'X-RapidAPI-Key': 'redacted',
'X-RapidAPI-Host': 'redacted'
}
};
const response = await axios.request(options);
const result = response.data.result;

const records = result.map(({ asin: { original, variant } , name, date: { date }, review, rating }) => {
date = new Date(date).toISOString();
return { original, variant, name, review, rating, date };
});
if (records.length) await csvWriter.writeRecords(records)
return records.length === 0; 
}
async function getAllReviews(asin) {
const header = ['asin', 'name', 'review', 'rating'].map((item) => ({ id: item, title: item }))
const csvWriter = createCsvWriter({
path: './ProductReviews.csv',
header: header
});
let done = false;
let page = 1;
while (!done) {
done = await getReviewPage(asin, page++, csvWriter);
}
return page-1
}
// test it with
getAllReviews('myASIN').then(pagesWritten => console.log(`wrote ${pagesWritten} pages`);
// run it one of two ways:
async function getAllReviewsForAllProducts(asinArray) {
// in parallel, though you might get throttled by the service...
return await Promise.all(asinArray.map(getAllReviews));
// OR sequentially
for (let asin of asinArray) {
await getAllReviews(asin)
}
}

最新更新