control JSON is undefined in Windows Phone WebBrowser (IE) - javascript

I am currently building an application on Windows Phone 7 using the WebBrowser control. The WebBrowser is navigated to a URL, but I also inject my own javascript into the control.
However the code which seems to work well on other platforms (WebView for Android and iOS) doesn't seem to work in the WebBrowser:
function parseToString(outObject)
{
var outJSON = null;
try{
if(outObject != null){
outJSON = JSON.stringify(outObject);
}
}
catch(err)
{
outJSON = err.message;
}
window.external.Notify(outJSON);
}
I found out that the "control JSON is undefined" is thrown in the try block.
Can someone recommend an alternative method for stringifying the JSON in the WebBrowser/IE? Furthermore, I cannot use external libraries as those javascripts are injected into the WebBrowser.

The WP7 browser does not supply a JSON object, so you will need to use a third party library in order to convert an object into a JSON string. I have used both of these in the past:
Douglas Crockford's JSON library.
The knockoutJS toJSON function.
See this related question:
Serializing to JSON in jQuery

I had the same problem, but then added the following to the top of the HTML document:
<!DOCTYPE html>
This unfortunately doesn't help if you don't have access to the HTML document and are only injecting JavaScript, but someone might find it useful.

Related

Best option for crawling a website that loads content via ajax [duplicate]

Please advise how to scrape AJAX pages.
Overview:
All screen scraping first requires manual review of the page you want to extract resources from. When dealing with AJAX you usually just need to analyze a bit more than just simply the HTML.
When dealing with AJAX this just means that the value you want is not in the initial HTML document that you requested, but that javascript will be exectued which asks the server for the extra information you want.
You can therefore usually simply analyze the javascript and see which request the javascript makes and just call this URL instead from the start.
Example:
Take this as an example, assume the page you want to scrape from has the following script:
<script type="text/javascript">
function ajaxFunction()
{
var xmlHttp;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert("Your browser does not support AJAX!");
return false;
}
}
}
xmlHttp.onreadystatechange=function()
{
if(xmlHttp.readyState==4)
{
document.myForm.time.value=xmlHttp.responseText;
}
}
xmlHttp.open("GET","time.asp",true);
xmlHttp.send(null);
}
</script>
Then all you need to do is instead do an HTTP request to time.asp of the same server instead. Example from w3schools.
Advanced scraping with C++:
For complex usage, and if you're using C++ you could also consider using the firefox javascript engine SpiderMonkey to execute the javascript on a page.
Advanced scraping with Java:
For complex usage, and if you're using Java you could also consider using the firefox javascript engine for Java Rhino
Advanced scraping with .NET:
For complex usage, and if you're using .Net you could also consider using the Microsoft.vsa assembly. Recently replaced with ICodeCompiler/CodeDOM.
In my opinion the simpliest solution is to use Casperjs, a framework based on the WebKit headless browser phantomjs.
The whole page is loaded, and it's very easy to scrape any ajax-related data.
You can check this basic tutorial to learn Automating & Scraping with PhantomJS and CasperJS
You can also give a look at this example code, on how to scrape google suggests keywords :
/*global casper:true*/
var casper = require('casper').create();
var suggestions = [];
var word = casper.cli.get(0);
if (!word) {
casper.echo('please provide a word').exit(1);
}
casper.start('http://www.google.com/', function() {
this.sendKeys('input[name=q]', word);
});
casper.waitFor(function() {
return this.fetchText('.gsq_a table span').indexOf(word) === 0
}, function() {
suggestions = this.evaluate(function() {
var nodes = document.querySelectorAll('.gsq_a table span');
return [].map.call(nodes, function(node){
return node.textContent;
});
});
});
casper.run(function() {
this.echo(suggestions.join('\n')).exit();
});
If you can get at it, try examining the DOM tree. Selenium does this as a part of testing a page. It also has functions to click buttons and follow links, which may be useful.
The best way to scrape web pages using Ajax or in general pages using Javascript is with a browser itself or a headless browser (a browser without GUI). Currently phantomjs is a well promoted headless browser using WebKit. An alternative that I used with success is HtmlUnit (in Java or .NET via IKVM, which is a simulated browser. Another known alternative is using a web automation tool like Selenium.
I wrote many articles about this subject like web scraping Ajax and Javascript sites and automated browserless OAuth authentication for Twitter. At the end of the first article there are a lot of extra resources that I have been compiling since 2011.
I like PhearJS, but that might be partially because I built it.
That said, it's a service you run in the background that speaks HTTP(S) and renders pages as JSON for you, including any metadata you might need.
Depends on the ajax page. The first part of screen scraping is determining how the page works. Is there some sort of variable you can iterate through to request all the data from the page? Personally I've used Web Scraper Plus for a lot of screen scraping related tasks because it is cheap, not difficult to get started, non-programmers can get it working relatively quickly.
Side Note: Terms of Use is probably somewhere you might want to check before doing this. Depending on the site iterating through everything may raise some flags.
I think Brian R. Bondy's answer is useful when the source code is easy to read. I prefer an easy way using tools like Wireshark or HttpAnalyzer to capture the packet and get the url from the "Host" field and the "GET" field.
For example,I capture a packet like the following:
GET /hqzx/quote.aspx?type=3&market=1&sorttype=3&updown=up&page=1&count=8&time=164330
HTTP/1.1
Accept: */*
Referer: http://quote.hexun.com/stock/default.aspx
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: quote.tool.hexun.com
Connection: Keep-Alive
Then the URL is :
http://quote.tool.hexun.com/hqzx/quote.aspx?type=3&market=1&sorttype=3&updown=up&page=1&count=8&time=164330
As a low cost solution you can also try SWExplorerAutomation (SWEA). The program creates an automation API for any Web application developed with HTML, DHTML or AJAX.
Selenium WebDriver is a good solution: you program a browser and you automate what needs to be done in the browser. Browsers (Chrome, Firefox, etc) provide their own drivers that work with Selenium. Since it works as an automated REAL browser, the pages (including javascript and Ajax) get loaded as they do with a human using that browser.
The downside is that it is slow (since you would most probably like to wait for all images and scripts to load before you do your scraping on that single page).
I have previously linked to MIT's solvent and EnvJS as my answers to scrape off Ajax pages. These projects seem no longer accessible.
Out of sheer necessity, I have invented another way to actually scrape off Ajax pages, and it has worked for tough sites like findthecompany which have methods to find headless javascript engines and show no data.
The technique is to use chrome extensions to do scraping. Chrome extensions are the best place to scrape off Ajax pages because they actually allow us access to javascript modified DOM. The technique is as follows, I will certainly open source the code in sometime. Create a chrome extension ( assuming you know how to create one, and its architecture and capabilities. This is easy to learn and practice as there are lots of samples),
Use content scripts to access the DOM, by using xpath. Pretty much get the entire list or table or dynamically rendered content using xpath into a variable as string HTML Nodes. ( Only content scripts can access DOM but they can't contact a URL using XMLHTTP )
From content script, using message passing, message the entire stripped DOM as string, to a background script. ( Background scripts can talk to URLs but can't touch the DOM ). We use message passing to get these to talk.
You can use various events to loop through web pages and pass each stripped HTML Node content to the background script.
Now use the background script, to talk to an external server (on localhost), a simple one created using Nodejs/python. Just send the entire HTML Nodes as string, to the server, where the server would just persist the content posted to it, into files, with appropriate variables to identify page numbers or URLs.
Now you have scraped AJAX content ( HTML Nodes as string ), but these are partial html nodes. Now you can use your favorite XPATH library to load these into memory and use XPATH to scrape information into Tables or text.
Please comment if you cant understand and I can write it better. ( first attempt ). Also, I am trying to release sample code as soon as possible.

Execute javascript without webview in Android

I'm trying to execute a JS fonction in my Android app.
The function is in a .js file on a website.
I'm not using webview, I want to execute the JS function because it sends the request i want.
In the Console in my browser i just have to do question.vote(0);, how can I do it in my app ?
UPDATE 2018: AndroidJSCore has been superseded by LiquidCore, which is based on V8. Not only does it include the V8 engine, but all of Node.js is available as well.
You can execute JavaScript without a WebView. You can use AndroidJSCore. Here is a quick example how you might do it:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://your_website_here/file.js");
HttpResponse response = client.execute(request);
String js = EntityUtils.toString(response.getEntity());
JSContext context = new JSContext();
context.evaluateScript(js);
context.evaluateScript("question.vote(0);");
However, this most likely won't work outside of a WebView, because I presume you are not only relying on JavaScript, but AJAX, which is not part of pure JavaScript. It requires a browser implementation.
Is there a reason you don't use a hidden WebView and simply inject your code?
// Create a WebView and load a page that includes your JS file
webView.evaluateJavascript("question.vote(0);", null);
For the future reference, there is a library by square for this purpose.
https://github.com/square/duktape-android
This library is a wrapper for Duktape, embeddable JavaScript engine.
You can run javascript without toying with WebView.
Duktape is Ecmascript E5/E5.1 compliant, so basic stuff can be done with this.

How can you access javascript variables from a C#.Net Webbrowser object?

I want to create a Webbrowser .Net object from my C#.Net Winform application and then be able to access javascript variables.
Basically I want to take some action in my main Winform application depending on some user interactions that happen that set javascript variables.
Any advice on how I can make calls to the Webbrowser object to do this?
Note I did look at the Document property that lets you get at the DOM but don't understand how/if that can be used to get at javascript variables.
Dan
In the WinForms browser, use the ObjectForScripting property to handle two-way communications between your WinForms application and your WebBrowser's Document.
You can invoke javascript members from C# through the Document object:
// C# code
webBrowser1.Document.InvokeScript("test",
new String[] { "called from client code" });
Assigning ObjectForScripting as
// C# code
webBrowser1.ObjectForScripting = obj;
appears to allow the hosted javascript to call members of obj, e.g.
// javascript code
window.external.SomeMethod('called from script code');
// executes obj.SomeMethod(string) in C#
Disclaimer: I only have experience with the WPF web browser, so I haven't verified the above myself.
Make use of CeSharp, a Chromium Embedded Framework that allows much more control over your webbrowser component.
To get started
Fire up a VS project
Open nuget console and execute: Install-Package CefSharp.WinForms if you are doing Winforms C# App.
Restart your Visual studio and re-load project.
Example of CefSharp code to get started.
Add a toolStripContainer to your form from the toolbox then use the following example code to load cefsharp browser component.
public Form1()
{
InitializeComponent();
var browser = new ChromiumWebBrowser("http://localhost:1071/");
browser.Dock = DockStyle.Fill;
toolStripContainer1.ContentPanel.Controls.Add(browser);
}
This should get you started, in order to talk to JS from C# you will need to make use of EvaluateScript interface.
Take a look at the following resource.
https://github.com/cefsharp/CefSharp/issues/368

Intercepting window.external.notify call from javascript in objective C

I need to intercept a javascript call to window.external.notify which is returning a security token string that I need to get into my objective C code. The javascript is being executed in a UIWebView. The script there looks like:
<script type="text/javascript">
try{
window.external.notify('{<extremely long dictionary as a JSON string>}');
}
catch(err){
alert("Error ACS50021: window.external.notify is not registered.");
}
</script>
I need to somehow get the JSON dictionary into a string in objective C. I've tried going through the method here: http://www.stevesaxon.me/posts/2011/window-external-notify-in-ios-uiwebview/; but it just seems to interfere with the rendering of the html/javascript page and also not capture the string (I don't have a handy acs identifier to check for to know I'm intercepting the right call). Other similar questions have been asked, but I haven't been able to get any working, many seem extremely hackish, and they are usually quite out of date. I've tried accessing the webview's html content, but the token isn't present there, because it's only sent through window.external.notify, which errors out with the alert that it isn't registered.
I know there's now a native JS->objC bridge in iOS 7, and I only need to support iOS 7+, but I've never used it and I can't seem to get that up and running either. It also appears to be mainly for having your own JS source files as part of your app, and not for communicating with a server through a UIWebView, but if I'm wrong about that, let me know.
Try this method.Here the page is redirected and the token is loaded using receive data method.

Using Parse's JavaScript framework with Google Apps Script

I would like to use the Parse framework directly in Google Apps Script and copied the following source code from Parse.com directly into my project.
However, it seems that there are some adjustments required to get this to work correctly. e.g. when running the following sample code...
function upload()
{
Parse.initialize("wCxiu8kyyyyyyyyyyyyyyyyy", "bTxxxxx8bxxxxxxxxx");
var TestObject = Parse.Object.extend("TestObjectJSSSSS");
var testObject = new TestObject();
testObject.save({foo: "bar"}, {
success: function(object) {
alert("yay! it worked");
}
});
}
… I get the error message TypeError: Cannot call method "getItem" of undefined.
which seems to relate to localStorage. I believe I should replace localStorage with a similar storage type available in Google Apps Script. Would that be possible and how would I need to adjust the Parse code?
What other adjustments would I need to get to the Parse framework to work in my Google Apps Script project?
I would suggest that using Parse REST API would be a far simpler solution and it is meant for such cases.

Categories

Resources