The error message that I keep getting is the following:
assert.js:92
throw new assert.AssertionError({
^
AssertionError: abnormal phantomjs exit code: -1073741819
at Console.assert (console.js:102:23)
at ChildProcess.<anonymous> (C:\Users\file_path...\node_modules\phantom\phantom.js:132:28)
at ChildProcess.emit (events.js:98:17)
at Process.ChildProcess._handle.onexit (child_process.js:810:12)
Program node app.js exited with code 8
The break happens at random, sometimes after inserting over a thousand rows into postgreSQL, sometimes after just a handful of rows.
I'm fairly sure that the error is occuring in the following function inside of my code, based on a lot of different console.logs that I have put throughout the code. Also, I think that assert.js:92 is from Chai:
function getNetworkTraffic(networkUrl,senderEmail) {
phantom.create(function (ph) {
ph.createPage(function (page) {
page.set("onResourceRequested", function (req) {
referrerValue = "";
referrerName = "";
linkRedirectUrl="";
console.log('Fetching network traffic...')
for (i in req.headers) {
allReferrals = req.headers[i]
if (allReferrals.name == "Referer"){
referrerName = allReferrals.name
referrerValue = allReferrals.value
}
}
linkUrl = req.url
if(req.redirectURL){
linkRedirectUrl = redirectURL
}
singleReq = {"referrerName":referrerName,"referrerValue":referrerValue,"requestUrl":linkUrl,"redirectURL":linkRedirectUrl, "parent_url":networkUrl, "source": "email", "senderEmail":senderEmail}
// insertNetworkTrafficPg(singleReq)
});
page.set("onResourceReceived", function (res) {
linkRedirectUrl = "";
responseUrl = res.url
if(res.redirectURL){
linkRedirectUrl = res.redirectURL
}
singleRes = {"responseUrl":responseUrl,"redirectURL":linkRedirectUrl,"parent_url":networkUrl,"source": "email", "senderEmail":senderEmail}
// insertNetworkTrafficPg(singleRes)
});
try{
page.open(networkUrl, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
}
console.log('Opening web address...');
ph.exit();
});
} catch(err) {
console.log(err)
}
});
}, {
dnodeOpts: {
weak: false
}
});
}
It's possible to use phantomjs with node, but keep in mind that this is a bridge. Also, it's really not intended for a lot of scraping, so perhaps you are opening too many threads and its a stackoverflow, but breaking with another message. You might want to try using something like python-shell to run a script for python to do your scraping.
Related
I'm creating a Discord bot, but have some problems catching the errors that my bot sends.
I'm using a custom command handler, that is working pretty well.
Fs.readFile(`./database/prefixes/prefixes.json`, "utf8", (err: Error, data): void => {
data = JSON.parse(data);
const prefix: string = data[message.author.id] == undefined ? "ma!" : data[message.author.id];
const msg: string = message.content;
const args: string[] = message.content.slice(prefix.length).trim().split(" ");
const cmd: string = args.shift().toLowerCase();
if (!msg.startsWith(prefix)) {
return checkCustomCommands();
}
let ops: {} = {
queue: queue
}
try {
require(checkFolders(cmd)).run(Client, message, args, ops); // maybe catching just there?
Logger.log(`${message.author.tag} just used the ${cmd} power in ${message.guild.name}.`);
} catch (err) {
Logger.log(`The command ${message.author.tag} tried to call in ${message.guild.name} doesen't seem to exist.`);
}
});
function checkCustomCommands() {
let content = JSON.parse(Fs.readFileSync('./database/commands/commands.json', 'utf8'));
try {
if (content[message.guild.id][message.content] == undefined) {
return;
} else {
message.channel.send(content[message.guild.id][message.content]);
}
} catch (err) {
return;
}
}
function checkFolders(command) {
let folders = ["moderation", "fun", "music", "info", "game"];
var files: string[];
var finalPath: string;
folders.forEach(folder => {
files = Fs.readdirSync(`./src/commands/${folder}`);
files.forEach(file => {
if (file.split(".")[0] == command) {
return finalPath = `./../commands/${folder}/${file.split(".")[0]}.js`;
}
});
});
return finalPath;
}
But sometimes, my bot sends various errors that I can't catch into the commands files, resulting in my bot being shutdown. Is there any way to prevent that inside the command handler, or anything I can do to catch these errors?
Thanks a lot, I can provide more code if needed, even though the biggest chunk of the command handler is just there ^
I'm quite late to this, but I feel like I should answer my own question, now that I'm able to do so haha
The main way to catch these errors is by listening to the unhandledRejection event, via Node process.
Here's how I did it:
async function handleRejections() {
process.on("unhandledRejection", (error: Error) => {
const errorEmbed: Discord.MessageEmbed = new Discord.MessageEmbed()
.setDescription("<:no:835565213322575963> An error has been detected... \n" + `\`\`\`${error.stack}\`\`\``)
.setTimestamp()
.setFooter(client.user.username, client.user.displayAvatarURL())
.setColor("DARK_RED")
logError(client, errorEmbed);
});
}
Be sure to call the function at the very beginning of the project code, even before the bot starts.
I personally log these errors into a Discord channel, on my server, so that I can check them easily. That's it! Hope that helps. Keep on coding :D
In ,winston when I tried logging by passing a mongoose query result as a metadata argument, winston just spit out like a thousand lines of log before the task quit.
So for a log like this :
tSchool.findById(bus.schoolid,function(err,school){
winston.info('loaded school',school);
});
Here's a small piece of whats get output :
return _next.apply(this, arguments);
}, remove=function wrappedPointCut() {
var args = [].slice.call(arguments);
var lastArg = args.pop();
var fn;
var originalStack = new Error().stack;
var $results;
if (lastArg && typeof lastArg !== 'function') {
args.push(lastArg);
} else {
fn = lastArg;
}
var promise = new Promise.ES6(function(resolve, reject) {
args.push(function(error) {
if (error) {
// gh-2633: since VersionError is very generic, take the
// stack trace of the original save() function call rather
// than the async trace
if (error instanceof VersionError) {
error.stack = originalStack;
}
_this.$__handleReject(error);
reject(error);
return;
}
// There may be multiple results and promise libs other than
// mpromise don't support passing multiple values to `resolve()`
$results = Array.prototype.slice.call(arguments, 1);
resolve.apply(promise, $results);
});
_this[newName].apply(_this, args);
});
if (fn) {
if (_this.constructor.$wrapCallback) {
fn = _this.constructor.$wrapCallback(fn);
}
return promise.then(
function() {
process.nextTick(function() {
fn.apply(null, [null].concat($results));
});
},
function(error) {
process.nextTick(function() {
fn(error);
});
});
}
return promise;
}
So I wanted to know a few things :
Why is passing a mongoose query result, which is supposed to be just a small json object, printing such gibberish?
Will this happen for other objects also - like the err objects in callbacks .etc?
How do I prevent this? Checking each and every log statement to ensure no query results are passed is not very practical.
Thanks in advance.
Update :
Issues #862, #474 and #914 are tracking/related to this problem, but there hasn't been much progress.
This issue has been fixed in pull request #977 of Winston. you can check out the details on the PR page.
I am using the sftps NPM to connect to a SFTP server using username/password authentication and upload a file. This works beautifully when successful; however, if provided invalid authentication information, after several minutes it emits an ECONNRESET error which crashes my entire application.
Looking at the source of the sftps module, it appears to use child_process.spawn to run the shell commands, and looks like it should be capturing any errors gracefully:
var sftp = spawn(shellCmd, shellOpts);
var data = "";
var error = "";
sftp.stdout.on('data', function (res) {
data += res;
});
sftp.stderr.on('data', function (res) {
error += res;
});
function finished(err) {
error = error.split('\n').filter(function(line) {
if (/^Connected to /.test(line)) return false;
return true;
}).join('\n');
data = data.split('\n').filter(function(line) {
if (/^sftp> /.test(line)) return false;
return true;
}).join('\n');
if (callback) {
if (err) {
callback(err, { error: error || null, data: data });
} else if (error) {
callback(null, { error: error, data: data });
} else {
callback(null, { error: null, data: data });
}
callback = null;
}
}
sftp.on('error', finished);
sftp.on('exit', function (code) {
if (code === 0) {
finished();
} else {
finished('Nonzero exit code: ' + code);
}
});
sftp.stdin.write(cmdString, 'utf8');
It looks like it has hooked into the stderr stream as well as capturing the error and exit events on the sub-process.
What else can I do to capture this ECONNRESET error and log it without killing the application?
Don't know if you're having the same problem that I was having, but I eventually solved it by attaching an event to stdin.on("error"). You could try this to see if that's the problem:
sftp.stdin.on("error", function (e)
{
console.log("STDIN ON ERROR");
console.log(e);
});
I have an weird error and can't find the cause of it for the last few hours...
I have a meteor app, that scrapes some webpages for information and everything works fine as long as I use reuqest and cheerio for static pages, but now I have a dynamic site and I wanted to use phantomjs, casperjs and spookyjs for this one, but here I get some bug...
My code is as follows, I import the npm modules at the start:
if (Meteor.isServer) {
var cheerio = Meteor.npmRequire('cheerio');
var request = Meteor.npmRequire('request');
var phantomJS = Meteor.npmRequire('phantomjs');
var spooky = Meteor.npmRequire('spooky');
And sometime later I want to use spooky to scrape some webpage:
spooky.start("https://www.coursera.org/");
spooky.then( function () {
this.fill("form", {email: user, password: pass}, true);
});`
But as soon as I call the method I get the following error message:
20150224-21:16:39.100(-5)? Exception while invoking method 'getLecturesCoursera' TypeError: Object function Spooky(options, callback) {
....
I20150224-21:16:39.281(-5)? } has no method 'start'
I20150224-21:16:39.281(-5)? at [object Object].Meteor.methods.getLecturesCoursera (app/moocis.js:72:14)
I am doing something completly wrong and I have no clue why it isn't working...
I tried to verify that spookyjs and phantomjs are installed correctly in my app, but that isn't as easy as it sounds for someone who uses them for the first time...
Like normally with spooky you have to create a new Spooky Object before you can start and run it...
if (Meteor.isServer) {
Meteor.startup( function () {
var Spooky = Meteor.npmRequire('spooky');
var spooky = new Spooky({
child: {
transport: 'http'
},
casper: {
logLevel: 'debug',
verbose: true,
ignoreSslErrors: true,
sslProtocol: 'tlsv1'
}
}, function (err) {
if (err) {
e = new Error('Failed to initialize SpookyJS');
e.details = err;
throw e;
}
spooky.start(
'https://www.google.com');
spooky.then(function () {
this.emit('hello', 'Hello, from ' + this.evaluate(function () {
return document.title;
}));
});
spooky.run();
});
spooky.on('error', function (e, stack) {
console.error(e);
if (stack) {
console.log(stack);
}
});
spooky.on('hello', function (greeting) {
console.log(greeting);
});
spooky.on('log', function (log) {
if (log.space === 'remote') {
console.log(log.message.replace(/ \- .*/, ''));
}
});
})
}
I have the following piece of code, but due to it's async behavior (I suppose), the callback is called twice. I'm using node-unzip to unzip a file I download from the internet.
function DownloadAndExtract(file, callback) {
log.debug("Starting download of "+file);
fse.ensureDirSync(tempPath);
var extractor = unzip.Extract({path: tempPath});
extractor.on("close", function() {
log.debug("Done downloading "+file);
return callback(null, file);
});
extractor.on("error", function (err) {
log.error("Extracting download "+file+": "+JSON.stringify(err, null, "\t"));
return callback(err, null); // THIS IS LINE 274
});
var url = "";
if(file == "WONEN") {
url = "https://example.com/file1.zip";
}else if(file == "BOG") {
url = "https://example.com/file2.zip";
}
if(url != "") {
request
.get(url)
.on("error", function (err) {
return callback(err, null);
})
.pipe(extractor);
}else{
return callback(new Error("Invalid file indicator: '"+file+"'"), null);
}
}
I expected return to actually quit all running async functions but that is obviously nonsense. Now, the error I keep getting is the following:
/home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:30
if (called) throw new Error("Callback was already called.");
^
Error: Callback was already called.
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:30:31
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:251:21
at /home/nodeusr/huizenier.nl/node_modules/async/lib/async.js:575:34
at Extract.<anonymous> (/home/nodeusr/huizenier.nl/realworks.js:274:10)
at Extract.emit (events.js:129:20)
at Parse.<anonymous> (/home/nodeusr/huizenier.nl/node_modules/unzip/lib/extract.js:24:10)
at Parse.emit (events.js:107:17)
at /home/nodeusr/huizenier.nl/node_modules/unzip/lib/parse.js:60:12
at processImmediate [as _immediateCallback] (timers.js:358:17)
The output of the log.error() call is the following:
21-02-2015 03:00:05 - [ERROR] Extracting download WONEN: {} so I'm quite confused. There isn't really an error, then why is the event emitted?
How would I prevent the callback from being called twice here? Contacting the creator of the package or create a work around?
Code calling DownloadAndExtract
async.parallel([
function (callback) {
DownloadAndExtract("WONEN", callback);
},
function (callback) {
DownloadAndExtract("BOG", callback);
}
],
function (err, done) {
if(err) return log.error("Update entries: "+JSON.stringify(err, null, "\t"));
// Do different logic if no error
});
Edit
One of my attempts is declaring a var callbackAlreadyCalled = false within the function, and at any given point where I call the callback, I do
if(!callbackAlreadyCalled) {
callbackAlreadyCalled = true;
return callback(callback params);
}
Is this a good approach or could I handle it in a better way?
Edit 2
Already found out that the empty error is caused by errors not working properly when using JSON.stringify(), however, problem doesn't change.
It looks like you have waterfall error calls.
When you call the request, it calls the extractor then if there is an error it calls the on_error of the extractor and then the on_error of the request.
Try to unify your returns from errors or call it only once. Make a test removing one of your "on('error'" validation.