How to Handle (Java-)Script Variables in Python? - javascript

This opens a new tab in Firefox browser:
from selenium import webdriver
browser = webdriver.Firefox()
browser.execute_script('''window.open("https://www.google.com/","_blank");''')
As a reference, here is the Selenium documentation:
**execute_script**(script, *args)
Synchronously Executes JavaScript in the current window/frame.
Args:
script: The JavaScript to execute.
*args: Any applicable arguments for your >JavaScript.
Usage:
driver.execute_script(‘return document.title;’)
I have a link in a String which I wish to open in a new tab using javascript (via execute_script).
Tried the following but it gives an error:
link = 'https://www.bing.com/'
java_script = '\'\'\'window.open(\"' + link + '\",\"_blank\");\'\'\''
browser.execute_script(script)
Error:
selenium.common.exceptions.JavascriptException: Message: SyntaxError: unexpected token: string literal

F-string are well suited for that check them out
This will change your code to look like this:
from selenium import webdriver
browser = webdriver.Firefox()
link = 'https://www.bing.com/'
browser.execute_script(f"window.open('{link}','_blank');")

Related

Can't narrow down correct element in Python/Selenium

So I'm trying to craft a website manipulation script to help automate teh creation of email mailboxes on our hosted provider.
I'm both new to Python and new to scripting web resources so if something looks weird or mediocre that's why :)
Here's my script:
import time
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium import webdriver
from selenium.webdriver.support.select import Select as driverselect
driver = webdriver.Firefox()
main_url = 'https://website.com:446'
opts = Options()
# noinspection PyDeprecation
# opts.set_headless()
#assert opts.headless # Operating in headless mode
browser = Firefox(options=opts)
browser.get(main_url)
search_form = browser.find_element_by_id('LoginName')
search_form.send_keys('username')
search_form = browser.find_element_by_id('Password')
search_form.send_keys('password')
search_form.submit()
time.sleep(5)
# provision = driverselect(driver.find_element_by_xpath("/html/body/div[2]/div[2]/nav/div/ul/li[4]"))
provision = driver.find_element_by_xpath('/html/body/div[2]/div[2]/nav/div/ul/li[4]/a/span[1]')
provision.submit()
# exchange = driver.find_element_by_name('Exchange')
# exchange.submit()
My error is:
Traceback (most recent call last): File
"/home/turd/PycharmProjects/Automate_NSGEmail/selenium_test.py", line
23, in provision =
driver.find_element_by_xpath('/html/body/div[2]/div[2]/nav/div/ul/li[4]/a/span1')
File "/home/turd/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",
line 394, in find_element_by_xpath
return self.find_element(by=By.XPATH, value=xpath) File "/home/turd/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",
line 976, in find_element
return self.execute(Command.FIND_ELEMENT, { File "/home/turd/.local/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",
line 321, in execute
self.error_handler.check_response(response) File "/home/turd/.local/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py",
line 242, in check_response
raise exception_class(message, screen, stacktrace) selenium.common.exceptions.NoSuchElementException: Message: Unable to
locate element: /html/body/div[2]/div[2]/nav/div/ul/li[4]/a/span1
Now that Xpath value I copied straight from the dev tools on that page, here's what this block of code looks like from the site:
I'm trying to grab and 'click' on the one Active Dynamic-Menu item in the pic above. I think that menu is JS but I'm not 100% positive.
Anyway I'd be much obliged if anyone could help me narrow this down and grab that blasted element.
So I discovered the answer myself.. I had some wrong code at the beginning of my script:
driver = webdriver.Firefox()
main_url = 'https://website.com:446'
opts = Options()
# noinspection PyDeprecation
# opts.set_headless()
#assert opts.headless # Operating in headless mode
browser = Firefox(options=opts)
browser.get(main_url)
I changed this section to:
driver = webdriver.Firefox()
url = 'https://website.com:446'
opts = Options()
driver.maximize_window()
driver.get(url)
I was opening two instances of Firebox before, the driver.* lines would attempting to locate the xpath tags on the FF instance that was not logged in.
Derp.

Selenium/BS4 JS execute raises "Message: TypeError: arguments[0].setAttribute is not a function"

I am using Selenium with BS4 to grab elements on a page and I want to use JS Execute_script to put a border around the element. However I am getting this error:
selenium.common.exceptions.JavascriptException: Message: TypeError: arguments[0].setAttribute is not a function
I've found this: Selenium Python bindings: how to execute JavaScript on an element?
I based it off this solution, which I got working when I grabbed the element using the Selenium - find_element_by_ID. It seems to be a different object type when getting an element as a soup object maybe?
P.S. when the object is not a string type its a <class 'bs4.element.Tag'>
Which raises a separate exception.
Any ideas, maybe I should go back to getting the elements through Selenium?
EDIT:
from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
browser = webdriver.Firefox()
browser.get('"https://www.glassdoor.com/Job/jobs.htm?suggestCount=0suggestChosen=false&clickSource=searchBtn&typedKeyword=&sc.keyword=&locT=C&locId=1132348&jobType="')
innerHTML = browser.execute_script("return document.body.innerHTML")
soup = BeautifulSoup(innerHTML)
browser.implicitly_wait(10)
def highlight_element():
#Use to highlight element selected
elem = soup.findAll("li", {"class": "jl"})
def apply_style():
browser.execute_script("arguments[0].setAttribute('style','border: 4px solid red');", str(elem[0]))
apply_style()
I tested with Chrome. I pass the browser and WebElement to the function and use find_element so no index required. Notice that elem is a webElement.
from selenium import webdriver
def apply_style(browser, elem):
browser.execute_script("arguments[0].setAttribute('style','border: 4px solid red');", elem)
browser = webdriver.Chrome()
browser.get('https://www.glassdoor.com/Job/jobs.htm?suggestCount=0suggestChosen=false&clickSource=searchBtn&typedKeyword=&sc.keyword=&locT=C&locId=1132348&jobType=')
browser.implicitly_wait(5)
apply_style(browser, browser.find_element_by_css_selector('.jl'))

executed_script failed to send long text despite send_keys works well [duplicate]

My code inputs text into the text area of the web page , line by line, how to make it insert the entire text all at once instead, is there a solution for this?
because line by line takes a lot of time
def Translated_Content(content):
driver= webdriver.Chrome("C:\\Users\\shricharan.arumugam\\Desktop\\PDF2txt\\chromedriver.exe")
driver.get('https://translate.shell.com/')
input_box = driver.find_element_by_id('translateText')
input_box.send_keys(content)
translate_button = driver.find_element_by_id('translate')
translate_button.click()
translated_text_element= driver.find_element_by_id('translatedText')
time.sleep(4)
translated_text=translated_text_element.get_attribute('value')
driver.close()
return translated_text
You can change the text of textbox/textarea through JavaScript DOM API in silent way, not from front UI:
long_string= <the long string>
input_box = driver.find_element_by_id('translateText')
driver.execute_script('arguments[0].value=arguments[1]', input_box, long_string)
To send the entire chunk of text into the <textarea> using selenium through Python to speed up the process you can inject a script and use the following solution:
Code Block:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
myText = """No, there is no way to hide the console window of the chromedriver.exe
in the .NET bindings without modifying the bindings source code. This is seen
as a feature of the bindings, as it makes it very easy to see when your code
hasn't correctly cleaned up the resources of the ChromeDriver, since the console window
remains open. In the case of some other languages, if your code does not properly clean up
the instance of ChromeDriver by calling the quit() method on the WebDriver object,
you can end up with a zombie chromedriver.exe process running on your machine."""
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument('disable-infobars')
driver=webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver.get('https://translate.shell.com/')
translate_from = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "textarea.form-control#translateText")))
translate_from._parent.execute_script("""
var elm = arguments[0], text = arguments[1];
if (!('value' in elm))
throw new Error('Expected an <input> or <textarea>');
elm.focus();
elm.value = text;
elm.dispatchEvent(new Event('change'));
""", translate_from, myText)
driver.find_element_by_css_selector("input#translate").click()
Browser Snapshot:

Using the JavascriptExecutor with Powershell

I've created several Powershell scripts that's using the Selenium Webdriver.
Now I need to add some Javascript functionality to one of them, but I'm unable to figure out how I go about to get the syntax correct.
Attempted to convert the following C# code from this discussion:
Execute JavaScript using Selenium WebDriver in C#
And this is what my code looks like at the moment:
# Specify path to Selenium drivers
$DriverPath = (get-item ".\" ).parent.parent.FullName + "\seleniumdriver\"
$files = Get-ChildItem "$DriverPath*.dll"
# Read in all the Selenium drivers
foreach ($file in $files) {
$FilePath = $DriverPath + $file.Name
[Reflection.Assembly]::LoadFile($FilePath) | out-null
}
# Create instance of ChromeDriver
$driver = New-Object OpenQA.Selenium.Chrome.ChromeDriver
# Go to example page google.com
$driver.Url = "http://www.google.com"
# Create instance of IJavaScriptExecutor
$js = New-Object IJavaScriptExecutor($driver)
# Run Javascript to get current url title
$title = $js.executeScript("return document.title")
# Write titel to cmd
write-host $title
But I constantly get the error below when creating instance of IJavaScriptExecutor:
"New-Object : Cannot find type [IJavaScriptExecutor]: make sure the assembly containing this type is loaded."
Can anyone figure out what I'm missing? Is it incorrect code? Missing additional dll's?
Br,
Christian
The problem is that IJavaScriptExecutor is an interface and you can't create an instance of an interface. Instead, you need to create an instance of a class which implements the interface. In this case, the ChromeDriver class implements this interface, so you could just skip the line which creates the $js variable and instead use the $driver.
So you'd get something like the following, given that your javascript function works as expected:
# Create instance of ChromeDriver
$driver = New-Object OpenQA.Selenium.Chrome.ChromeDriver
# Go to example page google.com
$driver.Url = "http://www.google.com"
# Run Javascript to get current url title
$title = $driver.executeScript("return document.title")
You can read more about these classes on the Selenium Documentation.

Selenium WebDriver Unable to Find Element by Id, Using Python

I'm trying to pull up an element that only gets created after the JavaScript runs, but I keep getting the following error message:
selenium.common.exceptions.NoSuchElementException: Message: u'Unable to locate element: {"method":"id","selector":"post-count"}' ; Stacktrace: Method FirefoxDriver.prototype.findElementInternal_ threw an error in file:///tmp/tmpittNsw/extensions/fxdriver#googlecode.com/components/driver_component.js
I'm trying to pull this element up on cnn.com. My code:
socket.setdefaulttimeout(30)
browser = webdriver.Firefox() # Get local session of firefox
browser.get(article_url_txt) # Load page
result = browser.find_element_by_id("post-count")
The element you are looking for is inside an iframe.
The following did the trick for me:
from selenium.webdriver.support.wait import WebDriverWait
# ...
frame = WebDriverWait(browser, 30).until(lambda x: x.find_element_by_id("dsq1"))
browser.switch_to_frame(frame)
result = WebDriverWait(browser, 30).until( lambda x: x.find_element_by_id("post-count"))
Note that I included the use of WebDriverWait(...).until(...) to allow the elements to be created dynamically just in case.
You can tell the WebDriver to wait implicitly until the element is visible.
browser.implicitly_wait(30)
result = browser.find_element_by_id("post-count")

Categories

Resources