how to get result from executing javascript in webpage using python - javascript

it is possible to get result from executing Javascript from website?
let say i have website www.test.com and inside that website they have script Javascript like
function fetchData(callback) {
var uriMatch = window.location.pathname.match(/\/([\w-]+)\.html/);
var uri = uriMatch ? uriMatch[1] : "";
var userAgent = navigator.userAgent;
var isAndroid = window.Env.isAndroid();
var isIOS = window.Env.isIos();
var deviceType = isAndroid ? "android" : isIOS ? "ios" : "pc";
var headerParams = {
"user-agent": userAgent,
};
var cookieParams = document.cookie.split("; ").reduce((obj, item) => {
var [k, v] = item.split("=");
obj[k] = v;
return obj;
}, {});
var params = new URLSearchParams(window.location.search);
var requestParams = {};
for (var p of params) {
var [k, v] = p;
requestParams[k] = v;
}
window.Mtop.default.request(
{
data: {
deviceType: deviceType,
path: window.location.href,
uri: uri,
headerParams: JSON.stringify(headerParams),
cookieParams: JSON.stringify(cookieParams),
requestParams: JSON.stringify(requestParams),
},
type: "POST",
v: "1.0",
needLogin: false,
api: "getDetailInfo",
},
function (res) {
if (res.data && res.data.module) {
var data = JSON.parse(res.data.module);
// this var data what i want to become my output
return data;
}
}
);
currently im using requests_html to rendering that script using this code
from requests_html import HTMLSession
session = HTMLSession()
req = session.get(url)
#js is variable string that script i want execute, same as previous javascript code
req.html.render(script=js, timeout=30, sleep=5)
html = req.html.html
soup = BeautifulSoup(html, 'html.parser')
that code is working fine, but how i can get result from script i have already execute

Related

how to handle string comparison and file writing using xlsx with nodejs

This script is to get the title of the webpage where the URL of the website will be passed from an excel file, check to see if the title contains the keyword, and then store that domain in the new excel file.
There is no issue with the partial code, but the title comparison does not work as expected. Does anyone have an idea how to fix it?
here is my code
var request = require("request");
var cheerio = require("cheerio");
const xlsx = require("xlsx");
jsonData = [{ Domain: "blogger.com" }, { Domain: "stackoverflow.com" }];
function fetchTitle(url, onComplete = null) {
request(url, function (error, response, body) {
var output = url; // default to URL
if (!error && (response && response.statusCode) === 200) {
var $ = cheerio.load(body);
console.log(`URL = ${url}`);
var title = $("head > title").text().trim();
console.log(`Title = ${title}`);
output = `[${title}] (${url})`;
var keywords = ["Developers", "blog"];
var results = [];
var UrlArray = [];
for (var i = 0; i < keywords.length; i++) {
var match = title.match(new RegExp(keywords.join("|"), "g"));
results.push(keywords[i]);
}
if (match.length > 0) {
UrlArray.push({
Domain: url,
Keywords: results,
Title: output,
});
finalJsonData = JSON.stringify(UrlArray);
const ws = xlsx.utils.json_to_sheet(UrlArray);
const wb = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(wb, ws, "Responses");
xlsx.writeFile(wb, "output.xlsx");
}
} else {
console.log(
`Error = ${error}, code = ${response && response.statusCode}`
);
}
console.log(`output = ${output} \n\n`);
if (onComplete) onComplete(output);
});
}
jsonData.forEach(function (table) {
var tableName = table.Domain;
var URL = "http://" + tableName;
fetchTitle(URL);
});
When I execute the script, I am able to get the title, but when I compare it with the keyword, it is not working as expected. Keywords are not being stored. You can see how the output looks after executing the script.
The script shows that both domains have keywords, but only blogger is stored in the spreadsheet, even then keywords aren't stored
you're overwriting the file on each loop,
keywords is an array, so it doesn't get saved, furthermore, keywords column will always contain all keywords, not the matching ones...
as requests are async, you need to track them all, and write results only when all requests are finished.
try this:
match case insensitive, and store only matching keywords for that site, not all (I also added "no match" for domains with no match)
store results outside the loop
move writing results into a separate function
add request counter and callback to track requests
write results when requests are done
the code:
var request = require("request");
var cheerio = require("cheerio");
const xlsx = require("xlsx");
const jsonData = [{ Domain: "blogger.com" }, { Domain: "stackoverflow.com" }];
var UrlArray = [];
function writeResults() {
const finalJsonData = JSON.stringify(UrlArray);
const ws = xlsx.utils.json_to_sheet(UrlArray);
const wb = xlsx.utils.book_new();
xlsx.utils.book_append_sheet(wb, ws, "Responses");
xlsx.writeFile(wb, "output.xlsx");
}
function fetchTitle(url, onComplete = null) {
request(url, function (error, response, body) {
var output = url; // default to URL
if (!error && (response && response.statusCode) === 200) {
var $ = cheerio.load(body);
console.log(`URL = ${url}`);
var title = $("head > title").text().trim();
console.log(`Title = ${title}`);
output = `[${title}] (${url})`;
var keywords = ["Developers", "blog"];
var results = [];
for (var i = 0; i < keywords.length; i++) {
let match = title.match(new RegExp(keywords[i], "gi"));
if (match && match.length > 0) {
results.push(keywords[i]);
}
}
UrlArray.push({
Domain: url,
Keywords: results.length > 0 ? results.join(', ') : 'no match',
Title: output,
});
} else {
console.log(
`Error = ${error}, code = ${response && response.statusCode}`
);
}
console.log(`output = ${output} \n\n`);
if (onComplete) onComplete(output);
});
}
let counter = 0;
jsonData.forEach(function (table) {
var tableName = table.Domain;
var URL = "http://" + tableName;
fetchTitle(URL, ()=>{
counter++;
if(counter === jsonData.length) {
console.log(`all ${counter} requests done`);
writeResults();
}
});
});

Function not being run after if statement in Chrome extension

I am making a Chrome extension for version 87.0.4280.66.
It's a little fun script library to mess around with apps.
Right now, I'm making a Chrome extension that when you click a button, it adds on to an Instructure link to make it play confetti.
I'm making it check if there are parameters present or not, as well as if it is an Instructure link too.
The problem is when I call the function, it doesn't run it at all.
Here is the popup.js that is responsible for updating the URL to add the parameter confetti=true.
let confetti = document.getElementById('confetti');
const regEx = /https:\/\/cbsd\.instructure\.com\/courses\/([0-9]{5})\/assignments\/([0-9]{6})\?module_item_id=([0-9]{7})|https:\/\/cbsd\.instructure\.com\/courses\/([0-9]{5})\/assignments\/([0-9]{6})/g;
var getParams = function (url) {
var params = {};
var parser = document.createElement('a');
parser.href = url;
var query = parser.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
params[pair[0]] = decodeURIComponent(pair[1]);
}
return params;
};
function error(message)
{
var notification = {
type: "basic",
title: "Error",
iconUrl: "images/error.ico",
message: message
}
chrome.notifications.create(notification);
}
function isCanvas(domain)
{
return regEx.test(domain);
}
function isMod(dom)
{
var parameters = getParams(dom);
if (parameters) {
return(true)
} else {
return(false)
}
}
confetti.onclick = function(element) {
chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
let domain = tabs[0].url;
var canvasCheck = isCanvas(domain)
if (canvasCheck === true) {
error(isMod(domain).toString());
/*/ if (andOrQuestion) {
let newUrl = domain + "&confetti=true";
chrome.tabs.update({url: newUrl});
} else {
let newUrl = domain + "?confetti=true"
chrome.tabs.update({url: newUrl});
} /*/
} else {
// error("You are not on an assignment page!")
}
});
}
Thank you for taking the time to answer this question and have a nice day!

How to filter by file path in Google apps script

I am trying to have the following script filter by file path. Ideally this should only show results from the folder marked 'GUEST' in my drive. Right now it shows those and anything else with the shared folder ID of this root (I do not want to use the GUEST folder ID because I will later use this to filter other users accessing my drive).
My google drive file path is as follows Root/GUEST
CODE UPDATED WITH ANSWER FROM COMMENTS:
var folderId = "MyID"; // <--- Your shared folder ID
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.data = getFileList();
return t.evaluate() .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);;
}
function getparams(e) {
return zipping(typeof(e.fileId) == "string" ? [e.fileId] : e.fileId);
}
function getFileList() {
var folderlist = (function(folder, folderSt, results) {
var ar = [];
var folders = folder.getFoldersByName("GUEST");
while (folders.hasNext()) ar.push(folders.next());
folderSt += folder.getId() + "#_aabbccddee_#";
var array_folderSt = folderSt.split("#_aabbccddee_#");
array_folderSt.pop()
results.push(array_folderSt);
ar.length == 0 && (folderSt = "");
for (var i in ar) arguments.callee(ar[i], folderSt, results);
return results;
})(DriveApp.getFoldersByName("GUEST").next(), "", []);
var localTimeZone = Session.getScriptTimeZone();
var filelist = [];
var temp = {};
for (var i in folderlist) {
var folderid = folderlist[i][folderlist[i].length - 1];
var folder = DriveApp.getFoldersByName("GUEST");
var files = folder.next().getFiles();
while (files.hasNext()) {
var file = files.next();
temp = {
folder_tree: function(folderlist, i) {
if (i > 0) {
return "/" + [DriveApp.getFolderById(folderlist[i][j]).getName() for (j in folderlist[i])
if (j > 0)].join("/") + "/";
} else {
return "/";
}
}(folderlist, i),
file_id: file.getId(),
file_name: file.getName(),
file_size: file.getBlob().getBytes().length,
file_created: Utilities.formatDate(file.getDateCreated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
file_updated: Utilities.formatDate(file.getLastUpdated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
};
filelist.push(temp);
temp = {}
}
}
var sortedlist = filelist.sort(function(e1, e2) {
return (e1.folder_tree > e2.folder_tree ? 1 : -1) });
return sortedlist;
}
function zipping(fileId) {
var blobs = [];
var mimeInf = [];
fileId.forEach(function(e) {
try {
var file = DriveApp.getFileById(e);
var mime = file.getMimeType();
var name = file.getName();
} catch (e) {
return e
}
Logger.log(mime)
var blob;
if (mime.indexOf('google-apps') > 0) {
mimeInf =
mime == "application/vnd.google-apps.spreadsheet" ? ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", name + ".xlsx"] : mime == "application/vnd.google-apps.document" ? ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", name + ".docx"] : mime == "application/vnd.google-apps.presentation" ? ["application/vnd.openxmlformats-officedocument.presentationml.presentation", name + ".pptx"] : ["application/pdf", name + ".pdf"];
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "/export?mimeType=" + mimeInf[0], {
method: "GET",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
}).getBlob().setName(mimeInf[1]);
} else {
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "?alt=media", {
method: "GET",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
}).getBlob().setName(name);
}
blobs.push(blob);
});
var zip = Utilities.zip(blobs, Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyyMMdd_HHmmss") + '.zip');
var bytedat = DriveApp.createFile(zip).getBlob().getBytes();
return Utilities.base64Encode(bytedat);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script>
function postLogin(event) {
var form = document.getElementById("myForm");
form.submit();
event.preventDefault();
}
</script>
<a href="" onClick="postLogin(event);" >Click!</a>
<form id="myForm" action="MYEXECLINK" target="my_iframe"></form>
<iframe id="my_iframe"name="my_iframe" style= "width: 500px; height: 50%;" frameBorder="0" style="overflow:hidden"></iframe>
I tried to use an if statement at line 61, but it could not pull the variables for some reason (I think I'm not setting up my variables correctly):
if (filelist(folder_tree == "/GUEST/"){
return sortedlist;}
else
{return null}
Does anyone know how to make this script filter by folder_tree? Hopefully by comparing it to a var (like user=guest)?
To clarify, here is the current result:
And this is the expected output:
Thanks for any help, I'll post updates as I work on it to clarify.
You want to retrieve a file list under the specific folder.
Subfolders in the specific folder are not required to be retrieved.
You want to achieve this using Google Apps Script.
I could understand like above. If my understanding is correct, how about this modification? I think that your updated script works. But I thought that your script might be able to be modified more simple. So how about the following modification?
Modification point:
In this modification, getFileList() was modified.
In your script, at first, the folder tree is retrieved. Then, the files in all folders are retrieved. But in your situation, the folder tree is not required to be retrieved. By this, your script can be modified more simple.
At first, "FileIterator" are retrieved with DriveApp.getFoldersByName("GUEST").next().getFiles(). Then, the values are retrieved from "FileIterator".
Modified script:
function getFileList() {
var folderName = "GUEST";
var files = DriveApp.getFoldersByName(folderName).next().getFiles();
var localTimeZone = Session.getScriptTimeZone();
var filelist = [];
while (files.hasNext()) {
var file = files.next();
var temp = {
file_id: file.getId(),
file_name: file.getName(),
file_size: file.getBlob().getBytes().length,
file_created: Utilities.formatDate(file.getDateCreated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
file_updated: Utilities.formatDate(file.getLastUpdated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
};
filelist.push(temp);
}
return filelist;
}
References:
getFoldersByName(name)
getFiles()
Class FileIterator

angularjs post data to mvc controller in json format with multiple arrays

I am working on a project in which I have used angularjs and mvc.I am passing data from angular js controller to my mvc controller by $http.post().For now I am using single object/json array to retreive data like this -public bool UpdateIssueDetails(IssueBO issue).But I want that if I could do like this public public bool UpdateIssueDetails(IssueBO issue,List lstMembersToNotify).I want to send two json arrays from ny angular js controller to my above mvc controller method.
angularjs controller code
$scope.saveIssueDetails = function (issue) {
var milestoneId = "";
var milestoneName = "";
if ($scope.selectedIssue.Milestone== undefined) {
milestoneId = "";
milestoneName = "";
} else {
milestoneId = $scope.selectedIssue.Milestone.Id;
milestoneName = $scope.selectedIssue.Milestone.Name;
}
var arrMembersToNotify = [];
var arrMembersToNotifyNew = [];
var iCount = 0;
$("#membersToNotify input[type=checkbox]:checked").each(function () {
arrMembersToNotify = $(this).val().split("~");
arrMembersToNotifyNew.push({ "UserId": arrMembersToNotify[0], "UserDisplayName": arrMembersToNotify[1], "Email": arrMembersToNotify[2] });
});
var issueDetails =
{
Id: issue.Id,
ProjectId: issue.ProjectId,
ProjectName: issue.ProjectName,
IssueStatusId: $scope.selectedIssue.Status.Id,
StatusName: $scope.selectedIssue.Status.Name,
IssuePriorityId: $scope.selectedIssue.Priority.Id,
PriorityName: $scope.selectedIssue.Priority.Name,
AssignedUserId: $scope.selectedIssue.AssignedTo.Id,
AssigneeDisplayName: $scope.selectedIssue.AssignedTo.DisplayName,
IssueCategoryId: $scope.selectedIssue.Category.Id,
CategoryName: $scope.selectedIssue.Category.Name,
DueDate: $scope.selectedIssue.DueDate,
OwnerUserId: $scope.selectedIssue.OwnedBy.Id,
OwnerDisplayName: $scope.selectedIssue.OwnedBy.DisplayName,
IssueTypeId: $scope.selectedIssue.Type.Id,
IssueTypeName: $scope.selectedIssue.Type.Name,
IssueResolutionId: $scope.selectedIssue.Resolution.Id,
ResolutionName: $scope.selectedIssue.Resolution.Name,
MilestoneId: milestoneId,
MilestoneName: milestoneName,
Estimation: $scope.selectedIssue.Estimation,
Progress: $scope.selectedIssue.Progress,
};
var url = window.location.protocol + '//' + window.location.host + '/api/Issues' + '/UpdateIssueDetails/';
$http.post(url, [issueDetails, arrMembersToNotifyNew]).success(function (data, status, headers, config) {
if (data != '' || data.length >= 0 || data == true) {
//$scope.selectedIssue = issue;
//$scope.showIssueDetails($scope.selectedIssue);
$scope.GetAssignedIssues();
}
else if (data == '' || data == false) {
$scope.selectedIssue = null;
} else {
$scope.errors.push(data.error);
}
});
};
mvc controller code
[HttpPost]
[AuthenticationRequired]
public bool UpdateIssueDetails(IssueBO issue,List<IssueNotification> lstMembersToNotify)
{
try
{
//var issueDetails = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(issueAllDetails[0].ToString());
//List<Dictionary<string, string>> membersToNotifyDetails = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(issueAllDetails[1].ToString());
var membersToNotify = lstMembersToNotify.Select(membersToNotifyDetail =>
new IssueNotification()
{
UserId =membersToNotifyDetail.UserId,
Email =
membersToNotifyDetail.Email,
UserDisplayName =
membersToNotifyDetail.UserDisplayName
}).ToList();
var newIssue = new IssueBO
{
OwnerUserId = issue.OwnerUserId,
OwnerDisplayName = issue.OwnerDisplayName,
LastUpdatedUserId = SessionItems.UserId,
LastUpdaterDisplayName = SessionItems.DisplayName,
LastUpdatedOn = DateTime.Now,
ProjectId = issue.ProjectId,
ProjectName = issue.ProjectName,
Id = issue.Id,
AssignedUserId = issue.AssignedUserId,
AssigneeDisplayName = issue.AssigneeDisplayName,
IssueStatusId = issue.IssueStatusId,
StatusName = issue.StatusName,
Progress = issue.Progress,
IssuePriorityId = issue.IssuePriorityId,
PriorityName = issue.PriorityName,
IssueTypeId = issue.IssueTypeId,
IssueTypeName = issue.IssueTypeName,
IssueCategoryId = issue.IssueCategoryId,
CategoryName = issue.CategoryName,
IssueResolutionId = issue.IssueResolutionId,
ResolutionName = issue.ResolutionName,
DueDate = issue.DueDate,
Estimation = issue.Estimation,
MilestoneId = issue.MilestoneId,
MilestoneName = issue.MilestoneName
};
var result = BLL.AdminLayer.UpdateIssueDetail(newIssue, membersToNotify);
return result.IsSuccessful && result.Result;
}
catch (Exception ex)
{
BLL.Base.BaseLayer.WriteApplicationLog(ex);
return false;
}
}
I am passing two json array from my angularjs controller like this-$http.post(url, [issueDetails, arrMembersToNotifyNew]).success(function (data, status, headers, config).But I am getting error trying this.Please suggest how to achieve this.Thanks
You need to pass data to the action by using JSON.stringify()
$http.post(url, JSON.stringify({ issue: issueDetails,
lstMembersToNotify: arrMembersToNotifyNew
});
Post it as properties of an object.
$http.post(url, { issue: issueDetails, lstMembersToNotify: arrMembersToNotifyNew });

Create json file using blob

I have written json code in string and i want to send it using xmlhttp as .json file. Is it possible to do it with blob?
var cleanScript = {
'type': 'script',
'api_key': api_key,
'data': data,
'inputs': inputs,
'timeoutSeconds': timeoutSeconds
};
var jsonse = JSON.stringify(cleanScript, null, 2);
Now json to blob?
Try something like this
var cleanScript = {
'type': 'script',
'api_key': api_key,
'data': data,
'inputs': inputs,
'timeoutSeconds': timeoutSeconds
};
var jsonse = JSON.stringify(cleanScript);
var blob = new Blob([jsonse], {type: "application/json"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = "backup.json";
a.textContent = "Download backup.json";
document.getElementById('json').appendChild(a);
<div id="json"></div>
Try the code below:
var int2ByteArray = function(i, minByteCount) {
var result = [],
buf = code = +i,
offsetCount = 0;
while ((buf = code>>(8 * offsetCount)) || offsetCount < minByteCount) {
buf = buf & 0xFF;
++offsetCount;
result.push(buf);
}
return result.reverse();
};
var ascii2ByteArray = function(s) {
if (!s) return 0;
var result = [];
[].map.call(s, function(c) {
result = result.concat(int2ByteArray((typeof(c)).toLowerCase() == "number" ? c : c.charCodeAt(0)));
});
return result;
};
// You got the blob here, do whatever you want.
var blob = new Blob(new Uint8Array(ascii2ByteArray(jsonse)), {type:"text/json"});
The matrix is to convert a string(stringfied by JSON.stringify) in to a Uint8Array that could be used making a blob.
I happened make something like that before, hope it's useful.

Categories