VBA & Selenium | Access iframe within HTML containing #document - javascript

I am trying to access the HTML within two iframes using Selenium Basic in VBA, as IE has been blocked on our machines, and Python, etc. are not available to us.
Previously I could access the html with this:
Dim IE As InternetExplorerMedium
Set IE = New InternetExplorerMedium
' actual website excluded as it is a work hosted website which requires login, etc.
website = "..."
IE.navigate (website)
Dim IEDocument As HTMLDocument
Set IEDocument = IE.document.getElementById(id1).contentDocument.getElementById(id2).contentDocument
From there I would have access to all the HTML elements which I could work with.
Now I am trying the following with Selenium Basic:
Set cd = New Selenium.ChromeDriver
website = "..."
cd.Start baseUrl:=website
cd.Get "/"
Dim af1 As Selenium.WebElement, af2 As Selenium.WebElement
Set af1 = cd.FindElementById("CRMApplicationFrame")
Set af2 = af1.FindElementById("WorkAreaFrame1")
It works up to the last line, as it is able to set af to the "CRMApplicationFrame" id; however, I am unable to get inside of it.
I think the solution lies in executing a bit of JavaScript, similar to as in this video:
https://www.youtube.com/watch?v=phYGCGXGtEw
Although I don't have a #ShadowDOM line, I do have a #document line.
Based on and trying to adapt the video I have tried the following:
Set af2 = cd.ExecuteScript(Script:="return arguments[0].contentDocument", arguments:=af1 )
However, that did not work.
I also tested:
Dim af1 As Selenium.WebElement
Set af1 = cd.FindElementById("CRMApplicationFrame")
call cd.SwitchToFrame (af1)
Debug.Print cd.PageSource
However, the SwitchToFrame line won't execute, with a 438 error: Object doesn't support this property or method.
Any advice or guidance on how I could succeed would be highly appreciated!

Replace:
call cd.SwitchToFrame (af1)
with:
cd.SwitchToFrame "CRMApplicationFrame"
You can find a relevant detailed discussion in Selenium VBA Excel - problem clicking a link within an iframe

Related

Get full URL of external website by JS, PHP or VBA

I am wondering is there a way to return full URL (or just params) of the website using JavaScript or PHP, or even VBA in Excel?
I can not preview this site in an iframe, because it gives me an error:
("frame-ancestors 'self'". error, Content Security Policy)
so I can't use window.location (probably because the Cross-Origin), I wonder how it can be done in the PHP or Excel VBA (how to use xmlhttp.Open in such case?), or with JS without returning the content itself. I don't need the content, but just the full URL or parameters, by knowing only a part of the URL.
I have the full list of ID's from the shop, so if it would be possible I could save a lot of typing for the reseller, because he uses ID in ordering specific stuff from his supplier. If I use the ID the website loads the content and changes the URL to a proper one - it looks like this (in the browser):
My request: https://exampledomain.com/product_id=11
After loading URL is: https://exampledomain.com/product_id=11&category=bikes&type=street
so the part I am interested in is &category=bikes&type=street, but also a full URL will be enough for further analyzing.
TO BE MORE PRECISE, here are working examples:
observe how the URL changes after the content is loaded, and I need to grab new, changed URL
https://www.olx.pl/oferta/CID767-IDCkB7E.html
https://www.google.pl/maps/place/Paris,+France/
https://www.openstreetmap.org/search?query=Warszawa
I think this is what you are after.
'Import Everything From a Web Page:
Sub Test()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
With IE
.Visible = True
.Navigate "http://your_link_here/" ' should work for any URL
Do Until .ReadyState = 4: DoEvents: Loop
x = .document.body.innertext
x = Replace(x, Chr(10), Chr(13))
x = Split(x, Chr(13))
Range("A1").Resize(UBound(x)) = Application.Transpose(x)
.Quit
End With
End Sub

Call VBScript from Node.js

To answer a request from the client, Node.js needs to export charts from Excel files in images into a repository.
I chose to use a VBA Macro because I don't think I have other solutions.
The VBA code is working properly (when I call it manually) but I wish I could connect it with Node.js events.
VBScript allows me to call a VBA Macro in my script.vbs file :
Option Explicit
On Error Resume Next
CallVBA
Sub CallVBA()
Dim ApplicationExcel
Dim ClasseurExcel
Set ApplicationExcel = CreateObject("Excel.Application")
Set ClasseurExcel = ApplicationExcel.Workbooks.Open("H:/macrosVBA.xlsm")
ApplicationExcel.Visible = False
ApplicationExcel.Run "ChartUpload"
ApplicationExcel.Quit
Set ClasseurExcel = Nothing
Set ApplicationExcel = Nothing
End Sub
My problem now is to run the VBScript in the JavaScript file :
var objShell = new ActiveXObject("WScript.shell");
objShell.run('H:/script.vbs');
I get the error :
ReferenceError: ActiveXObject is not defined
Adding win32ole and winax doesn't change anything, they don't seem to work anymore.
I'm looking for your help to have another solution or to fix my error with ActiveXObject.
Thanks in advance
Your Node.js is probably 64bit, whilst your Office/Excel is probably the 32bit version.
You need to run the 32bit VBScript interpreter in order to access the 32bit CreateObject("Excel.Application")
const { spawn } = require("child_process");
const bat = spawn("C:\\Windows\\SysWOW64\\wscript.exe", ["H:\\script.vbs"]);

Information inside Html Node not visible

I am trying to grab a phone number from a node from a website. For some reason when I inspect the node in chrome the actual number inside of the element is not visible. Here is the website that I am attempting to grab the number from: https://tempophone.com/ . Am I inspecting the wrong element or is it just not possible to grab the phone number from the website by accessing the node. Here is my code, I am using htmlAgilityPack:
string url = "https://tempophone.com/";
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load(url);
var phoneNumber = doc.DocumentNode.SelectNodes("//*[#id=\"temporary - phone\"]")[0].InnerText;
if(phoneNumber != null)
Console.WriteLine(phoneNumber);
else
Console.WriteLine("null");
Here is a screenshot of the inspected element, as you can see there is no phone number there:
Firstly there is no text inside that node.
Second what you want is this.
string s = doc.DocumentNode.SelectNodes("//*[#id='temporary-phone']")[0].GetAttributeValue("value", "false");
Third. This will always return "Loading...". Because the attribute 'value' in the node is updated/changed by the use javascript. When you use HtmlWeb or HttpWebRequest you will ALWAYS get the source of the page. If you want to be able to load dynamic content into your HtmlDocument you will need to use WebBrowser or Selenium with WebDriver.
How-to with Selenium and FirefoxDriver
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("https://tempophone.com/");
Thread.Sleep(2000);
driver.FindElement(By.XPath("//button[#id='check-phone']")).Click();
string s = driver.FindElement(By.XPath("//h1[#id='phone-number']")).GetAttribute("data-phone-number");
Console.WriteLine("Here: " + s);
Or you could just call their API
https://tempophone.com/api/v1/phones/random

What is wrong with my javascript for a browser I would like to create?

I know you people will think I am insane, and thus an idiot, but I really have a serious question, well at least to me. What is wrong with my javascript for a browser I would like to create?It will not open the URL in the iframe. I am creating an html source file with some javascript to split a "get" url,and echo the resulting variable into an iFrame. I wanna use Webkit as the rendering engine, so I'm using Google Chrome to create an application shortcut. Yes, I know it will require google chrome, but this is just a test.
function goTo(){
var urlb = window.location.href;
var urla = urlb.split('localhost/browser.html?url=');
var urlc = urla[1];
var urld = urlc.replace("+"," ");
var urle = urld.replace("%3A ",":");
var urlg = urle.replace("%2F","/");
var url = urlg;
document.getElementByID('url').innerHTML="<iframe src=' . url . "'width='100%'
height='90%'></iframe> Opened:" . url ."</div>";
}
This is the javscript function to open the url. I am pretty sure you would think that the html is just a simple input form and the blank Iframe, which it is.
Please help me if you can.
When you are trying to get the URL, you want to use decodeURIComponent(). Don't make up your own function to unescape the data. Also, get the query string parameters properly. See this StackOverflow post: https://stackoverflow.com/a/901144/362536
Now that you have the proper URL, don't simply inject it into your HTML. You're opening yourself up to security troubles, and a broken browser when you run into characters you don't expect. Create the iframe, then set its attributes programmatically. https://stackoverflow.com/a/710347/362536
Finally, fix your syntax errors.

how do I dump an html page as XML with watir & JavaScript?

I have been trying to create a simple script in FireWatir that will convert the entire current document DOM's (including javascript generated code) to XML representation .
following leads on the web I've came up with this script
require 'rubygems'
require 'firewatir'
browser = Watir::Browser.new
browser.goto('http://www.google.com/')
browser.text_field(:id, 'lst-ib').set('hello')
browser.button(:name, 'btnG').click
puts browser.execute_script("new XMLSerializer().serializeToString(document)")
however, running it in Firefox 3.6 , resulted in this error :
c:/Ruby192/lib/ruby/gems/1.9.1/gems/firewatir-1.9.2/lib/firewatir/jssh_socket.rb
:19:in js_eval': XMLSerializer is not defined (JsshSocket::JSReferenceError)
from c:/Ruby192/lib/ruby/gems/1.9.1/gems/firewatir-1.9.2/lib/firewatir/firefox.rb:136:inexecute_script' from test.rb:9:in `'
if I enter this line:
javascript:window.open('aout:blank').document.write('<pre>' + unescape((new XMLSerializer()).serializeToString(document).replace(/</g, '<')) + '</pre>')
into FF location box, I get a page with the desired XML. so XMLSerializer has to be defined somewhere, its just seems out of reach for my JS code.
how can I get this to work?
Not sure what you mean by "location box", but if that is address bar (the one that says http://stackoverflow.com/... at this page), then try this:
browser.goto "javascript:window.open('aout:blank').document.write('<pre>' + unescape((new XMLSerializer()).serializeToString(document).replace(/</g, '<')) + '</pre>')"
A t the core of it, I suspect this might be an FF thing to do with boundaries of the 'sandbox' that javascript is running in. The browser itself may know about the serializer, but not choose to give javascript any access to it.
However, there may be more than one way to skin the cat. If your second bit of code provides you with a page that is rendered as text in XML syntax, why not do that first, and then just use the resulting page via
puts browser.text

Categories

Resources