如何附加 json 而不重复(包括 CasperJS 代码)?
How to append json with no duplicating (including CasperJS code)?
我正在使用 CasperJS 解析网页的内部文本并保存到 json 文件。
这是我的代码,我会在下面向您展示结果(我遇到的问题)!
var words = [];
var casper = require('casper').create();
var x = require('casper').selectXPath;
var fs = require('fs');
function getWords() {
var words = document.querySelectorAll('span.inner_tit');
return Array.prototype.map.call(words, function(e) {
return e.innerHTML;
});
}
function createFinal(wordArray) {
var out = [];
wordArray.forEach(function(word) {
out.push({"type": "river", "name": word, "spell": word.length});
});
return out;
}
casper.start('http://dic.daum.net/index.do?dic=kor');
casper.thenClick(x('//*[@id="searchSubmit"]'), function(){
console.log('searching');
});
casper.wait(2000, function() {
casper.then(function() {
words = this.evaluate(getWords);
});
});
casper.wait(3000, function() {
casper.thenClick(x('//*[@id="mArticle"]/div[2]/a[2]'), function (){
words = words.concat(this.evaluate(getWords));
});
});
casper.run(function() {
var my_object = { "my_initial_words": createFinal(words)};
this.echo(JSON.stringify(my_object, null, '\t'))
var result = JSON.stringify(my_object, null, '\t')
fs.write('myresults.json', result, 'a');
this.exit();
});
这段代码的问题是,当我有 json 这样的代码时,
{
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
}
我的代码附加了所有内容,包括像这样的 json 数组的名称!
{
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
} {
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
}
所以..我不需要全部添加但只想添加这些元素! (没有 "my _initial_words: []")
{"type": "river", "name": "apple","spell": "5"},
{"type": "river", "name": "banana","spell": "6"}
正在更新文件中的对象
JSON 的定义方式使您无法将对象附加到现有对象并期望从中获得有效的 JSON。但是你可以
- 读取之前序列化的JSON字符串,
- 解析成一个对象,
- 将您的新值附加到数组,
- 再次序列化对象并
- 用它完全覆盖现有文件。
例如像这样:
var previousDataString = fs.read('myresults.json');
var previousData = JSON.parse(previousDataString);
previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
var newData = JSON.stringify(previousData, null, '\t')
fs.write('myresults.json', newData, 'w');
正在将块写入文件
如果您仍想将数据文件写成 JSON 的单独块,那么您可以这样做:
// Combine all items into a single string
var newItemsString = createFinal(words).reduce(function(combinedString, currentItem){
return combinedString + JSON.stringify(currentItem) + "\n";
}, "")
// append new items to previous items
fs.write('myresults.json', newItemsString, 'a');
每个项目(单词的对象)都写在一行上。当您在其他进程中读取文件时,您可以使用 readLine()
等函数一次只读取一项。
修复过早退出
您还必须牢记退出 CasperJS 的方式。如果您向 casper.run()
提供回调,则需要显式调用 casper.exit()
才能退出进程。问题是你做得太早了:
this.echo(JSON.stringify(previousData, null, '\t')).exit();
// ^^^^^^^ calling exit
var newData = JSON.stringify(previousData, null, '\t'); // not executed
fs.write('myscript.json', newData, 'w'); // not executed
要么你需要把退出放在回调的最后:
this.echo(JSON.stringify(previousData, null, '\t'));
var newData = JSON.stringify(previousData, null, '\t');
fs.write('myscript.json', newData, 'w');
this.exit();
或者不要将最终代码放入 casper.then()
而不是 casper.run()
:
casper.then(function() {
var previousDataString = fs.read('myscript.json');
var previousData = JSON.parse(previousDataString);
previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
this.echo(JSON.stringify(previousData, null, '\t'));
var newData = JSON.stringify(previousData, null, '\t')
fs.write('myscript.json', newData, 'w');
});
casper.run();
我正在使用 CasperJS 解析网页的内部文本并保存到 json 文件。
这是我的代码,我会在下面向您展示结果(我遇到的问题)!
var words = [];
var casper = require('casper').create();
var x = require('casper').selectXPath;
var fs = require('fs');
function getWords() {
var words = document.querySelectorAll('span.inner_tit');
return Array.prototype.map.call(words, function(e) {
return e.innerHTML;
});
}
function createFinal(wordArray) {
var out = [];
wordArray.forEach(function(word) {
out.push({"type": "river", "name": word, "spell": word.length});
});
return out;
}
casper.start('http://dic.daum.net/index.do?dic=kor');
casper.thenClick(x('//*[@id="searchSubmit"]'), function(){
console.log('searching');
});
casper.wait(2000, function() {
casper.then(function() {
words = this.evaluate(getWords);
});
});
casper.wait(3000, function() {
casper.thenClick(x('//*[@id="mArticle"]/div[2]/a[2]'), function (){
words = words.concat(this.evaluate(getWords));
});
});
casper.run(function() {
var my_object = { "my_initial_words": createFinal(words)};
this.echo(JSON.stringify(my_object, null, '\t'))
var result = JSON.stringify(my_object, null, '\t')
fs.write('myresults.json', result, 'a');
this.exit();
});
这段代码的问题是,当我有 json 这样的代码时,
{
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
}
我的代码附加了所有内容,包括像这样的 json 数组的名称!
{
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
} {
"my_initial_words": [
{
"type": "river",
"name": "apple",
"spell": "5"
},
{
"type": "river",
"name": "banana",
"spell": "6"
}
]
}
所以..我不需要全部添加但只想添加这些元素! (没有 "my _initial_words: []")
{"type": "river", "name": "apple","spell": "5"},
{"type": "river", "name": "banana","spell": "6"}
正在更新文件中的对象
JSON 的定义方式使您无法将对象附加到现有对象并期望从中获得有效的 JSON。但是你可以
- 读取之前序列化的JSON字符串,
- 解析成一个对象,
- 将您的新值附加到数组,
- 再次序列化对象并
- 用它完全覆盖现有文件。
例如像这样:
var previousDataString = fs.read('myresults.json');
var previousData = JSON.parse(previousDataString);
previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
var newData = JSON.stringify(previousData, null, '\t')
fs.write('myresults.json', newData, 'w');
正在将块写入文件
如果您仍想将数据文件写成 JSON 的单独块,那么您可以这样做:
// Combine all items into a single string
var newItemsString = createFinal(words).reduce(function(combinedString, currentItem){
return combinedString + JSON.stringify(currentItem) + "\n";
}, "")
// append new items to previous items
fs.write('myresults.json', newItemsString, 'a');
每个项目(单词的对象)都写在一行上。当您在其他进程中读取文件时,您可以使用 readLine()
等函数一次只读取一项。
修复过早退出
您还必须牢记退出 CasperJS 的方式。如果您向 casper.run()
提供回调,则需要显式调用 casper.exit()
才能退出进程。问题是你做得太早了:
this.echo(JSON.stringify(previousData, null, '\t')).exit();
// ^^^^^^^ calling exit
var newData = JSON.stringify(previousData, null, '\t'); // not executed
fs.write('myscript.json', newData, 'w'); // not executed
要么你需要把退出放在回调的最后:
this.echo(JSON.stringify(previousData, null, '\t'));
var newData = JSON.stringify(previousData, null, '\t');
fs.write('myscript.json', newData, 'w');
this.exit();
或者不要将最终代码放入 casper.then()
而不是 casper.run()
:
casper.then(function() {
var previousDataString = fs.read('myscript.json');
var previousData = JSON.parse(previousDataString);
previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
this.echo(JSON.stringify(previousData, null, '\t'));
var newData = JSON.stringify(previousData, null, '\t')
fs.write('myscript.json', newData, 'w');
});
casper.run();