I’m trying to solve this task:
a) Follow the link https://datatables.net/ by entering “Datatables” in Google search and By clicking on the right result.
b) You will find an example of a table with some data. Remove data from the table to the array. In the array you will have objects. The object will be a string from the table. The properties of the object will be data from each column of the table.
c) Please export an array as CSV.
As I never worked with Nightmare.js, I googled and found exactly what I need https://github.com/xandergriff /.com/blob/master/main.mjs , but at the beginning this code did not work, and I changed it a little , but still there is a mistake.
Here is a modified code:
// package definitions
var csvwriter = require ('CSV-Write-Stream');
var fs = require ('fs');
var Nightmare = Require ('nightmare');
// Constant Definitions.
Const Google = 'https://www.google.com';
const Query = 'Datatables';
const searchbar = 'form [Action * = "/ Search"] [Name = Q]';
const searchButton = 'FORM [ACTION * = "/ SEARCH"] [type = submit]';
const search_result_id = 'h3.r & gt; a ';
const datatables_link = 'https://datatables.net/';
const datatables_size_selector = 'select [Name = "Example_Length"]';
const datatables_data_selector = 'Table # Example TR';
(async () = & gt; {
Let Nightmare;
Try {
Nightmare = Nightmare ({show: true});
Await Nightmare.
// navigate to google
.gooto (Google)
.Type (SearchBar, Query)
SEARCHBUTTON)
.wait (search_result_id)
await nightmare.evaluate ((search_result_id,
Datatables_link) = & gt; {
Filter Results Based On CSS Selectors to Choose Link WITH
Proper Url.
// Indexed At 0 to Access Element From Single-Element Array
PRODUCED IN ABOVE INSTRUCTION
(Array.From (search_result_id)). Filter (A
= & gt; a.href === datatables_link) [0] .Click ();
}, Search_result_id, datatables_link)
// Adjust Datatable To Show All Entries
Await Nightmare.
.wait (datatables_size_selector)
.select (datatables_size_selector, 100);
// Retrieve Values From Datatable
AWAIT NIGHTMARE.EVALUATE ((datatable_data_selector) = & gt; {
Let Table_Rows =.
Array.from (datatables_data_selector));
// Delineate Between Keys and Vals From Retrieved Table Data
Let Table_Keys_ROW =.
Array.from (((Table_ROWS [0]). QuerySelectorall ('Th'). Map (E = & GT;
e.innerhtml); // Array Of Strings
Let Table_Data_Rows = Table_RowS.Slice (1.58); // Array.
Of Array of Html Elements
Let Array_of_ROW_Objects = [];
Let Row_Object = {};
Let Formatted_Values = [];
table_data_rows.Foreach (ROW = & GT; {
// Grab Innerhtml from Each Element in the Row
Formatted_Values =.
Array.From (Row.QuerySelectorall ('TD')). Map (E = & GT; E.innerhtml);
// Place Each of The Element Values in An Object With Each Value
Associated WITH its Respective Key
row_object = {};
For (i = 0; i & lt; table_keys_row.length; i ++) {
Row_Object [Table_KEYS_ROW [i]] =
Formatted_Values [i];
}
array_of_row_objects.push (Row_Object);
})
Return Array_of_ROW_Objects;
}, Datatables_data_selector)
// Write to CSV
Writer.pipe (FS.CREATEWRITESTREAM ('OUTPUT.CSV'));
Result.Foreach (OBJ = & GT; {
Writer.Write (OBJ);
});
writer.end ();
console.log ("Wrote values to CSV ...")
} catch (error) {
console.error (error);
throw error;
} finally {
await nightmare.end ();
}
}) ();
I run the code with DEBUG = nightmare and I get this:
nightmare queuing process start + 0ms
nightmare queueing action "goto" for https://www.google.com + 3ms
nightmare queueing action "type" + 0ms
nightmare queueing action "click" + 0ms
nightmare queueing action "wait" + 0ms
nightmare running + 1ms
nightmare queueing action "evaluate" + 5s
nightmare running + 1ms
{TypeError: Cannot read property 'click' of undefined
at fn (& lt; anonymous & gt;: 8: 106)
at javascript (& lt; anonymous & gt;: 23: 21)
at & lt; anonymous & gt;: 38: 3
at EventEmitter.electron.ipcRenderer.on (/home/anna/automation/node_modules/electron/dist/resources/electron.asar/renderer/web-frame-init.js:36:30)
at emitMany (events.js: 147: 13)
at EventEmitter.emit (events.js: 224: 7) code: -1}
nightmare running + 12ms
nightmare electron child process exited with code 0: success! + 55ms
(node: 10610) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'click' of undefined
at fn (& lt; anonymous & gt;: 8: 106)
at javascript (& lt; anonymous & gt;: 23: 21)
at & lt; anonymous & gt;: 38: 3
at EventEmitter.electron.ipcRenderer.on (/home/anna/automation/node_modules/electron/dist/resources/electron.asar/renderer/web-frame-init.js:36:30)
at emitMany (events.js: 147: 13)
at EventEmitter.emit (events.js: 224: 7)
(node: 10610) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch (). (rejection id: 1)
(node: 10610) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I don’t understand how to fix the error with click ()
due to my inexperience with nightmare.js, please help.
Answer 1
var csvWriter = require ('csv-write-stream');
var writer = csvWriter ();
var fs = require ('fs');
var Nightmare = require ('nightmare');
(async () = & gt; {
let nightmare;
try {
nightmare = Nightmare ({show: true});
await nightmare
.goto ('https://www.google.com')
.type ('form [action * = "/ search"] [name = q]', 'datatables')
.click ('form [action * = "/ search"] [type = submit]')
.wait (2500)
await nightmare.evaluate (() = & gt; {
var link = document.querySelector (". r a");
link.click ();
})
await nightmare
.wait ('select [name = "example_length"]')
.select ('select [name = "example_length"]', 100);
await nightmare.evaluate (() = & gt; {
let tableRows = Array.from (document.querySelectorAll ('table # example tr'));
let tableKeysRow = Array.from ((tableRows [0]). querySelectorAll ('th')). map (e = & gt; e.innerHTML);
let tableDataRows = tableRows.slice (1.58);
let arrayOfRowObjects = [];
let rowObject = {};
let formattedValues = [];
tableDataRows.forEach (row = & gt; {
formattedValues = Array.from (row.querySelectorAll ('td')). map (e = & gt; e.innerHTML);
rowObject = {};
for (i = 0; i & lt; tableKeysRow.length; i ++) {
rowObject [tableKeysRow [i]] = formattedValues [i];
}
arrayOfRowObjects.push (rowObject);
})
return arrayOfRowObjects;
})
.then (result = & gt; {
writer.pipe (fs.createWriteStream ('outputData.csv'));
result.forEach (obj = & gt; {
writer.write (obj);
});
writer.end ();
})
} catch (error) {
Console.error (Error);
Throw Error;
} finally {
await nightmare.end ();
}
}) ();