使用Nodejs / Papa Parse解析远程CSV文件?

时间:2017-12-14 22:45:45

标签: node.js csv parsing papaparse

我目前正致力于从Node应用程序解析远程csv产品供稿,并希望使用Papa Parse来做到这一点(因为我过去在浏览器中取得了成功)。

Papa Parse Github:https://github.com/mholt/PapaParse

我最初的尝试和网络搜索尚未确切地说明了如何做到这一点。 Papa自述文件说Papa Parse现在与Node兼容,因此Baby Parse(以前用于提供某些节点解析功能)已被折旧。

以下是指向未来遇到此问题的任何人的文档“节点”部分的链接:https://github.com/mholt/PapaParse#papa-parse-for-node

从该doc段开始,看起来Node中的Papa Parse可以解析可读流而不是文件。我的问题是;

  

有没有办法利用可读流功能来使用Papa在Node中下载/解析远程CSV,这与浏览器中Papa如何使用XMLHttpRequest实现同样的目标类似?

未来可见性 对于那些搜索主题(并避免重复类似问题)的人,试图利用此处描述的远程文件解析功能:http://papaparse.com/docs#remote-files将导致控制台出现以下错误:

"未处理拒绝ReferenceError:未定义XMLHttpRequest"

我已在官方存储库上打开了一个问题,并会在我了解有关需要解决的问题的更多信息时更新此问题。

6 个答案:

答案 0 :(得分:6)

好的,所以我想我有一个答案。但我想只有时间会证明。 请注意,我的文件是带有制表符分隔符的.txt。

var fs = require('fs');
var Papa = require('papaparse');
var file = './rawData/myfile.txt';
// When the file is a local file when need to convert to a file Obj.
//  This step may not be necissary when uploading via UI
var content = fs.readFileSync(file, "utf8");

var rows;
Papa.parse(content, {
    header: false,
    delimiter: "\t",
    complete: function(results) {
        //console.log("Finished:", results.data);
    rows = results.data;
    }
});

答案 1 :(得分:3)

经过大量的修改,我终于有了使用流的工作示例。请参见下面的示例:

const papa = require("papaparse");
const request = require("request");

const options = {/* options */};

const dataStream = request.get("https://example.com/myfile.csv");
const parseStream = papa.parse(papa.NODE_STREAM_INPUT, options);

dataStream.pipe(parseStream);

let data = [];
parseStream.on("data", chunk => {
    data.push(chunk);
});

parseStream.on("finish", () => {
    console.log(data);
    console.log(data.length);
});

parseStream的“数据”事件针对CSV中的每一行运行一次。希望这对某人有帮助!

另外:要使用本地文件而不是远程文件,您可以执行相同的操作,但要使用

fs.createReadStream("./myfile.csv").pipe(parseStream);

代替请求。

答案 2 :(得分:2)

实际上你可以使用lightweight stream transformation library called scramjet - 直接从http流解析CSV是我的主要例子之一。它还使用PapaParse来解析CSV。

上面所写的所有内容中的任何变换都可以在几行中完成:

const {StringStream} = require("scramjet");
const request = require("request");

request.get("https://srv.example.com/main.csv")   // fetch csv
    .pipe(new StringStream())                       // pass to stream
    .csvParse()                                   // parse into objects
    .consume(object => console.log("Row:", object))  // do whatever you like with the objects
    .then(() => console.log("all done"))

在您自己的示例中,您将文件保存到磁盘,即使使用PapaParse也不需要。

答案 3 :(得分:1)

我正在添加这个答案(并会在我进步时更新)以防其他人仍在调查此事。

似乎以前的用户首先下载文件然后再处理它。这不应该是必要的,因为Papa Parse应该能够处理一个读取流,并且应该可以管理' http' GET到那个流。

以下是有人讨论我要做的事情并回到下载文件然后解析它的一个实例:https://forums.meteor.com/t/processing-large-csvs-in-meteor-js-with-papaparse/32705/4

注意:在上面讨论的Baby Parse中,现在Papa Parse与Node Baby Parse一起工作已被折旧。

下载文件解决方法

  

虽然下载然后用Papa Parse进行解析不是我的问题的答案,但它是我现在唯一的解决方法,而其他人可能想要使用这种方法。

我下载然后解析的代码看起来像这样:

// Papa Parse for parsing CSV Files
var Papa = require('papaparse');
// HTTP and FS to enable Papa parse to download remote CSVs via node streams.
var http = require('http');
var fs = require('fs');

var destinationFile = "yourdestination.csv";

var download = function(url, dest, cb) {
  var file = fs.createWriteStream(dest);
  var request = http.get(url, function(response) {
    response.pipe(file);
    file.on('finish', function() {
      file.close(cb);  // close() is async, call cb after close completes.
    });
  }).on('error', function(err) { // Handle errors
    fs.unlink(dest); // Delete the file async. (But we don't check the result)
    if (cb) cb(err.message);
  });
};

download(feedURL, destinationFile, parseMe);

var parseMe = Papa.parse(destinationFile, {
  header: true,
  dynamicTyping: true,
  step: function(row) {
    console.log("Row:", row.data);
  },
  complete: function() {
    console.log("All done!");
  }
});

答案 4 :(得分:1)

Http(s)实际上在回调中具有可读的流作为参数,因此这是一个简单的解决方案

 try {
    var streamHttp = await new Promise((resolve, reject) =>
       https.get("https://example.com/yourcsv.csv", (res) => {
          resolve(res);
       })
    );
 } catch (e) {
    console.log(e);
 }

 Papa.parse(streamHttp, config);

答案 5 :(得分:0)

const Papa = require("papaparse");
const { StringStream } = require("scramjet");
const request = require("request");

const req = request
  .get("https://example.com/yourcsv.csv")
  .pipe(new StringStream());

Papa.parse(req, {
  header: true,
  complete: (result) => {
    console.log(result);
  },
});