urls returns an empty array []
I don't quite understand this part of the code myself as its borrowed,
I either need help understanding the urls part to recode it properly,
or have someone recode it for me which I will try my best to understand.
the urls part was made for google images but Im using another site.
im grabbing images of this site: https://www.desktopnexus.com/search/kitsune+girl/1/
function kitsuneimage(message) {
var options = {
url: "https://www.desktopnexus.com/search/" + "kitsune+girl" + "/" + Math.ceil(Math.random() * (60 + 2)) +"/",
method: "GET",
headers: {
"Accept": "text/html",
"User-Agent": "Chrome"
}
}
console.log(options.url);
request(options, function(error, response, responseBody) {
if (error) {
return;
}
$ = cheerio.load(responseBody);
var links = $(".image a.link");
var urls = new Array(links.length).fill(0).map((v, i) => links.eq(i).attr("href"));
console.log(urls);
if (!urls.length) {
return;
};
message.channel.send(urls[0]);
});
}
instead of
var links = $(".image a.link")
maybe this should work:
var thumbnails = $("#middlecolumn .thumbnail")
// this is a jquery object, so we need to call get() to turn it into a plain array
var links = thumbnails.map(thumbnail => thumbnail.parent()).get()
var urls = links.map(link => link.getAttribute('href'))
well the thumbnails part does grab the image and it looks like this in the console.log(thumbnails);
'2': {
type: 'tag',
name: 'img',
namespace: 'http://www.w3.org/1999/xhtml',
attribs: [Object: null prototype] {
src: '//cache.desktopnexus.com/thumbseg/1853/1853748-200.jpg',
border: '1',
alt: 'girl',
class: 'thumbnail'
},
but it says in the .parent is undefined
I was thinking maybe replace thumbnail with tag since thats the type it is, would that work?
----EDIT----
well thats wrong because thumbnail is the class of the image in this.
so why is .parent undefined?
This question is closed since I moved on to making a new code with "got" module
Related
I'm fetching data using API and Im receiving an array of objects. I want to extract the Timestamp & Result to CSV file. Im unsure how could I access those objects and how to store them in CSV as Im a beginner of javascript, any advise would be very much appreciated
My code:
const url = "https://api2.branch.io/v1/query/analytics";
await fetch(url, {
method: "POST",
headers: {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36",
Accept: "application/json; charset=UTF-8"
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then((data) => {
Object.keys(data).forEach(key => {
console.log(data[key]);
});
})
.catch(error => {
console.log(error);
})
};
//callback function
callApi();
The output of the console.log(data[key]):
[
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'Broad',
last_attributed_touch_data_tilde_advertising_partner_name: 'Google',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 7483928
}
},
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'Today',
last_attributed_touch_data_tilde_advertising_partner_name: 'Yahoo',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 43535345
}
},
{
timestamp: '2021-05-04T00:00:00.000+08:00',
result: {
last_attributed_touch_data_tilde_campaign: 'IOS',
last_attributed_touch_data_tilde_advertising_partner_name: 'Facebook',
last_attributed_touch_data_tilde_campaign_id: null,
unique_count: 747473
}
}
]
You first need to convert all data into CSV format. Here's one way you can do this, added comments to help you understand what is happening:
// where the csv data will be saved to
let csv = [];
// loops through each object in the 'data' array
for (let i = 0; i < data.length; i++) {
// this builds the CSV headers as the first line of the csv data
// i === 0 makes sure to only target the first object in the 'data' array
if (i === 0) {
let title = [];
// adds 'timestamp' key to the title array
title.push('timestamp');
// loops through all the 'result' keys, adds them to the growing title array
for (let key in data[i].result) {title.push(key);}
// format then collapses the array into a string, separated by commas to the csv array
// ex: ['A', B'] turns into "A, B"
csv.push(title.map(function(item) {return '' +item + '';}).join(', '));
}
// this builds the CSV data after the first line
let row = [];
// adds the 'timestamp' value to the row array
row.push(data[i].timestamp);
// loops through all the 'result' key's data, adds them to the growing row array
for (let key in data[i].result) {row.push(data[i].result[key]);}
// formats then collapses the array into a string, separated by commas to the csv array
csv.push(row.map(function(item) {return '' +item + '';}).join(', '));
}
// collapses the csv array into a string, separated by a newline break
// ex: ['A', 'B'] turns into "A\nB"
csv = csv.join('\n');
Then you need to download the data in a CSV file format.
function downloadAsCsv(csv, file_name) {
var blob = new Blob([csv], {'type':'text/csv;charset=utf-8;'});
// Internet Explorer 10+
if (navigator.msSaveBlob) {window.navigator.msSaveBlob(blob, file_name);}
else {
var link = document.createElement('a');
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', file_name);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
Here's a full working example: https://jsfiddle.net/th5vejLc/
I searched a lot on StackOverflow posts and able to figure out my program up to this level, however, I am unable to proceed forward. Need your suggestions on this if you can advise.
I am running a get API by taking in 2 request URLs one after the other using a URL array and using for loop to process each URL and send it to request.get and able to see the responses in the console.
However, the issue is with when I try to write the request URL and its corresponding response to file using the test case names serially from test case name array.
It's only writing the file with TC2_reqres.json and putting the request response of the first call.
Expecting something like this
TC1_reqres.json contains /people/1 response
TC2_reqres.json contains /people/2 response
Please suggest.
Thanks! much to all of ya in advance.
var request = require("request");
var fs = require('fs');
describe('testsuite', function () {
it("test case", function (done) {
var urlarr = ["https://swapi.co/api/people/1", "https://swapi.co/api/people/2"];
var tcnamearr = ["TC1", "TC2"];
var respath = "C:/Study_JSR/capi/tests/Res/";
for (var i = 0; i < tcnamearr.length; i++) {
url = urlarr[i];
tcname = tcnamearr[i];
request.get({ url: url, "rejectUnauthorized": false, "json": true }, function (e, r, user) {
resbod = JSON.stringify(user);
console.log("resbod: " + resbod);
fs.writeFileSync(respath + tcname + "_reqres.json", resbod);
})
}
done();
});
});
Try instead of var to use let
for (let i = 0; i < tcnamearr.length; i++) {
Javascript has strange behaviour with closures and async calls. The for loop completes before the callbacks are called so the value of tcname is always "TC2".
You should try to refactor the code.
Use axios instead of request. It support promises and it's better in these scenarios.
One possible solution is this:
var request = require("axios");
var fs = require('fs');
describe('testsuite', function () {
it("test case", function (done) {
var respath = "C:/Study_JSR/capi/tests/Res/";
var gets = [
request.get({ url: "https://swapi.co/api/people/1", "rejectUnauthorized": false, "json": true }),
request.get({ url: "https://swapi.co/api/people/2", "rejectUnauthorized": false, "json": true })
]
Promise.all(gets).then(function(res) {
fs.writeFileSync(respath + "TC1" + "_reqres.json", res[0].body)
fs.writeFileSync(respath + "TC2" + "_reqres.json", res[1].body)
})
done();
});
});
It's just a starting point, you can remove duplications if you need.
I'm trying to use the new Fetch API:
I am making a GET request like this:
var request = new Request({
url: 'http://myapi.com/orders',
method: 'GET'
});
fetch(request);
However, I'm unsure how to add a query string to the GET request. Ideally, I want to be able to make a GET request to a URL like:
'http://myapi.com/orders?order_id=1'
In jQuery I could do this by passing {order_id: 1} as the data parameter of $.ajax(). Is there an equivalent way to do that with the new Fetch API?
A concise, modern approach:
fetch('https://example.com?' + new URLSearchParams({
foo: 'value',
bar: 2,
}))
How it works: When a string (e.g. the URL) is being concatenated with an instance of URLSearchParams, its toString() method will automatically be called to convert the instance into a string representation, which happens to be a properly encoded query string. If the automatic invoking of toString() is too magical for your liking, you may prefer to explicitly call it like so: fetch('https://...' + new URLSearchParams(...).toString())
A complete example of a fetch request with query parameters:
// Real example you can copy-paste and play with.
// jsonplaceholder.typicode.com provides a dummy rest-api
// for this sort of purpose.
async function doAsyncTask() {
const url = (
'https://jsonplaceholder.typicode.com/comments?' +
new URLSearchParams({ postId: 1 }).toString()
);
const result = await fetch(url)
.then(response => response.json());
console.log('Fetched from: ' + url);
console.log(result);
}
doAsyncTask();
If you are using/supporting...
IE: Internet Explorer does not provide native support for URLSearchParams or fetch, but there are polyfills available.
Node: As of Node 18 there is native support for the fetch API (in version 17.5 it was behind the --experimental-fetch flag). In older versions, you can add the fetch API through a package like node-fetch. URLSearchParams comes with Node, and can be found as a global object since version 10. In older version you can find it at require('url').URLSearchParams.
Node + TypeScript: If you're using Node and TypeScript together you'll find that, due to some technical limitations, TypeScript does not offer type definitions for the global URLSearchParams. The simplest workaround is to just import it from the url module. See here for more info.
Update March 2017:
URL.searchParams support has officially landed in Chrome 51, but other browsers still require a polyfill.
The official way to work with query parameters is just to add them onto the URL. From the spec, this is an example:
var url = new URL("https://geo.example.org/api"),
params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)
However, I'm not sure Chrome supports the searchParams property of a URL (at the time of writing) so you might want to either use a third party library or roll-your-own solution.
Update April 2018:
With the use of URLSearchParams constructor you could assign a 2D array or a object and just assign that to the url.search instead of looping over all keys and append them
var url = new URL('https://sl.se')
var params = {lat:35.696233, long:139.570431} // or:
var params = [['lat', '35.696233'], ['long', '139.570431']]
url.search = new URLSearchParams(params).toString();
fetch(url)
Sidenote: URLSearchParams is also available in NodeJS
const { URL, URLSearchParams } = require('url');
let params = {
"param1": "value1",
"param2": "value2"
};
let query = Object.keys(params)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
.join('&');
let url = 'https://example.com/search?' + query;
fetch(url)
.then(data => data.text())
.then((text) => {
console.log('request succeeded with JSON response', text)
}).catch(function (error) {
console.log('request failed', error)
});
As already answered, this is per spec not possible with the fetch-API, yet. But I have to note:
If you are on node, there's the querystring package. It can stringify/parse objects/querystrings:
var querystring = require('querystring')
var data = { key: 'value' }
querystring.stringify(data) // => 'key=value'
...then just append it to the url to request.
However, the problem with the above is, that you always have to prepend a question mark (?). So, another way is to use the parse method from nodes url package and do it as follows:
var url = require('url')
var data = { key: 'value' }
url.format({ query: data }) // => '?key=value'
See query at https://nodejs.org/api/url.html#url_url_format_urlobj
This is possible, as it does internally just this:
search = obj.search || (
obj.query && ('?' + (
typeof(obj.query) === 'object' ?
querystring.stringify(obj.query) :
String(obj.query)
))
) || ''
You can use stringify from query-string.
import { stringify } from 'query-string';
fetch(`https://example.org?${stringify(params)}`)
encodeQueryString — encode an object as querystring parameters
/**
* Encode an object as url query string parameters
* - includes the leading "?" prefix
* - example input — {key: "value", alpha: "beta"}
* - example output — output "?key=value&alpha=beta"
* - returns empty string when given an empty object
*/
function encodeQueryString(params) {
const keys = Object.keys(params)
return keys.length
? "?" + keys
.map(key => encodeURIComponent(key)
+ "=" + encodeURIComponent(params[key]))
.join("&")
: ""
}
encodeQueryString({key: "value", alpha: "beta"})
//> "?key=value&alpha=beta"
I know this is stating the absolute obvious, but I feel it's worth adding this as an answer as it's the simplest of all:
const orderId = 1;
fetch('http://myapi.com/orders?order_id=' + orderId);
Maybe this is better:
const withQuery = require('with-query');
fetch(withQuery('https://api.github.com/search/repositories', {
q: 'query',
sort: 'stars',
order: 'asc',
}))
.then(res => res.json())
.then((json) => {
console.info(json);
})
.catch((err) => {
console.error(err);
});
Solution without external packages
to perform a GET request using the fetch api I worked on this solution that doesn't require the installation of packages.
this is an example of a call to the google's map api
// encode to scape spaces
const esc = encodeURIComponent;
const url = 'https://maps.googleapis.com/maps/api/geocode/json?';
const params = {
key: "asdkfñlaskdGE",
address: "evergreen avenue",
city: "New York"
};
// this line takes the params object and builds the query string
const query = Object.keys(params).map(k => `${esc(k)}=${esc(params[k])}`).join('&')
const res = await fetch(url+query);
const googleResponse = await res.json()
feel free to copy this code and paste it on the console to see how it works!!
the generated url is something like:
https://maps.googleapis.com/maps/api/geocode/json?key=asdkf%C3%B1laskdGE&address=evergreen%20avenue&city=New%20York
this is what I was looking before I decided to write this, enjoy :D
Template literals are also a valid option here, and provide a few benefits.
You can include raw strings, numbers, boolean values, etc:
let request = new Request(`https://example.com/?name=${'Patrick'}&number=${1}`);
You can include variables:
let request = new Request(`https://example.com/?name=${nameParam}`);
You can include logic and functions:
let request = new Request(`https://example.com/?name=${nameParam !== undefined ? nameParam : getDefaultName() }`);
As far as structuring the data of a larger query string, I like using an array concatenated to a string. I find it easier to understand than some of the other methods:
let queryString = [
`param1=${getParam(1)}`,
`param2=${getParam(2)}`,
`param3=${getParam(3)}`,
].join('&');
let request = new Request(`https://example.com/?${queryString}`, {
method: 'GET'
});
Was just working with Nativescript's fetchModule and figured out my own solution using string manipulation.
Append the query string bit by bit to the url. Here is an example where query is passed as a json object (query = {order_id: 1}):
function performGetHttpRequest(fetchLink='http://myapi.com/orders', query=null) {
if(query) {
fetchLink += '?';
let count = 0;
const queryLength = Object.keys(query).length;
for(let key in query) {
fetchLink += key+'='+query[key];
fetchLink += (count < queryLength) ? '&' : '';
count++;
}
}
// link becomes: 'http://myapi.com/orders?order_id=1'
// Then, use fetch as in MDN and simply pass this fetchLink as the url.
}
I tested this over a multiple number of query parameters and it worked like a charm :)
Hope this helps someone.
var paramsdate=01+'%s'+12+'%s'+2012+'%s';
request.get("https://www.exampleurl.com?fromDate="+paramsDate;
vm.imageR = $resource("", {}, {
getFile: {
url: '/api/imager/:fileId',
method: 'GET',
transformResponse: function(data, headersGetter) { return { data : data }},
isArray: false,
params: {
fileId: '#fileId'
}
},
...
This is what I receive:
"�PNG
IHDRX�7�"�PLTE���V�3R�-���O�(��������������S�/���P�*��h�H��������θ����������奥���ᴴ�����ށ�����O�E������...
How to correctly parse the image to display as image in HTML (set as src in image)?
If you really have to load the image this way, you will have to base64 the image data being returned on the server side and append that string on your img src.
// in this format
var imgData = "data:image/png;base64,"+theBase64Data;
Otherwise you will have to use an image tag to perform the request.
var img = document.createElement("img");
img.src = '/api/imager/'+fieldId; // whatever the fieldId is
// append it to the dom.
The second option make more sense since you are getting the image from the server anyway, why base64 it?
It's weird, but this was the only change that worked:
Before:
vm.getFile = function (fileId) {
return vm.imageR.getFile({ fileId: fileId });
};
Now:
vm.getFile = function (fileId) {
var retVal = vm.imageR.getFile({ fileId: fileId });
return retVal;
};
Really weird. :)
Why does the following:
$("a").sortable( {
update:function() {
var urls = "";
$.map($("a"), function(elt) {
urls += "url=" + elt.href + "&";
});
$.ajax( {
url: 'server_side_process_one.aspx',
type: 'POST',
data: { urls.substr(0,urls.length - 1) },
success: function() { alert(urls.substr(0,urls.length - 1)); }
});
}
});
return paths in the following format:
file:///C:/Program%20Office/OFFICE11/WINWORD.EXE
but the following:
$("input:checkbox").live('change', function() {
var that = this;
$.ajax({
url: 'server_side_process_two.aspx',
type: 'POST',
data: { $(that).attr("id") },
success: function() { alert($(that).attr("id")); }
});
});
returns path in the following format:?
C:\Program Files\Microsoft
Office\OFFICE11\WINWORD.EXE
Any idea how to get both functions to return in the same format? Preferably both should return in the basic format without all the extra characters, i.e.
C:\Program Files\Microsoft
Office\OFFICE11\WINWORD.EXE
but not
file:///C:/Program%20Office/OFFICE11/WINWORD.EXE
When you asks for an element's href, you'll get a version of this attribute, processed and cleaned by the browser. So, it really depends on what your aspx script does, but be sure that the URL you're passing to you script through strURLs is something with the appropiate URI, like file:///C:/Program%20Office/OFFICE11/WINWORD.EXE, and not an incorrect and malformed URL like C:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE.
Don't forget that you can see what you're sending to your script using tools like FireBug in Firefox.
Good luck!
This may just "patch" your problem, but you might just let the upper C# function return "file:///C:/Program%20Office/OFFICE11/WINWORD.EXE"... and then correct the formatting.
string sRtn = "file:///C:/Program%20Office/OFFICE11/WINWORD.EXE";
sRtn = sRtn.Replace("file:///", "");
sRtn = sRtn.Replace("/", "\");
sRtn = sRtn.Replace("%20", " ");