Selenium WebDriver Unable to Find Element by Id, Using Python - javascript

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")

Related

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

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');")

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:

Selenium Webdriver not executing JavaScript

I'm trying to scrape data from Aliexpress product page. example.
I need this section. (transaction history)
my code:
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
my_url = 'https://www.aliexpress.com/item/Cosmetic-Brush-Makeup-Blusher-Eye-Shadow-Kabuki-Brushes-Set-Tool-Kit-22pcs/32765190537.html?ws_ab_test=searchweb0_0'
chrome_options = Options()
chrome_options.add_argument("--enable-javascript")
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get(my_url)
innerHTML = driver.execute_script('return document.getElementsByTagName("html")[0].innerHTML')
page_html = driver.page_source
When i run
document.getElementsByTagName("html")[0].innerHTML
on the chrome console i get the entire html including the section that i need.
but, the innerHTML object give me the same html as driver.page_source (without the section that i need)
as far as i know this section is not under iFrame.
Some help please :-)
You probably want to look for this specific table.
Using
innerHTML = document.querySelectorAll('table.transaction-feedback-table');
Will probably find it
The trasactions is generated after the element ID j-transaction-feedback is visible, you have to scroll to the element and wait Ajax request finished.
from selenium.webdriver.support.ui import WebDriverWait
....
....
driver.get(my_url)
# scroll to the element
driver.find_element_by_css_selector('#j-transaction-feedback').location_once_scrolled_into_view
# wait until Ajax finished and render the element
transaction = WebDriverWait(driver, 15).until(
lambda d: d.find_element_by_css_selector('.transaction-feedback-content')
)
total_transaction = driver.find_element_by_css_selector('#j-transaction-feedback .text')
page_source = driver.page_source
print('total_transaction: ' + total_transaction.text)

Insert a script at the top of HEAD tag in PageMod (Firefox Add-on SDK)

I want to insert a script in Firefox Add-on SDK content script added via page-mod. So, when user goes to page XXX, he gets a page with the inserted script. But, when trying to insert this at the top of HEAD, I got an error that the 1st Node child is not an object.
My content script code with which I insert the <script> is:
script='<script>var d=new Date(2012,2,24); window.Date=function () {return d;}</script>';
var head = document.getElementsByTagName("head")[0];
head.insertBefore(script, head.firstChild);
What's with it?
You have not provided a Minimal, Complete, and Verifiable Example. Thus, this answer is based just on the code you have provided.
Issue with how you are using insertBefore():
The first issue I noticed is that you are providing a string as the first argument to insertBefore() when that argument needs to be a node object.
However, you state the error you are getting is "1st Node child is not an object". This does not match what I would expect from an error based on the code provided. When I put your code in a page-mod content script, the error I got was:
console.error: testpagemodinsertBefore:
Object
- _errorType = TypeError
- message = Argument 1 of Node.insertBefore is not an object.
- fileName = resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://testpagemodinsertbefore/data/contentScript.js
- lineNumber = 26
- stack = #resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/commonjs/sdk/loader/sandbox.js -> resource://testpagemodinsertbefore/data/contentScript.js:26:1|
- name = TypeError
This is the error which I would expect from the code in the question. Thus, you have either not posted the code which is producing the error you have stated, or you have inaccurately reported the error which you saw in the console. In the future, please be exact in what you are reporting. Being more verbose is better than leaving things out.
Inserting HTML text:
Your code:
script='<script>var d=new Date(2012,2,24); window.Date=function () {return d;}</script>';
defines some HTML text which you are trying to insert into the DOM.
If you want to insert HTML text instead of inserting nodes, one way for you to do so is to use insertAdjacentHTML(). One way you could do this in your code is:
head.insertAdjacentHTML('afterbegin',script);
This works well for most HTML. But, does not result in the contents of the <script> tag being executed/evaluated. This is for security reasons. It is much easier for an attacker to get arbitrary text inserted into the DOM than it is for them to insert actual nodes/elements. The HTML specification specifies that a tag inserted inserted as text will not be executed.
Inserting a <script> tag that is evaluated and executed:
We can do this by creating a <script> element containing the script text desired, then inserting that element into the DOM.
For your code that would look something like:
//Get the first <head> element
let head = document.getElementsByTagName("head")[0];
//The script text desired
let scriptText='var d=new Date(2012,2,24); window.Date=function () {return d;};';
//Add an alert for testing (\n is not needed. But, is more readable when inspecting DOM.)
scriptText = 'window.alert("In inserted script");\n' + scriptText;
//Create a <script> element
let scriptEl = document.createElement( 'script' );
//That is JavaScript
scriptEl.type = 'text/javascript';
//Add the script text
scriptEl.textContent = scriptText;
//Insert it as the firstChild of <head>
head.insertBefore( scriptEl, head.firstChild );
Further reading:
You appear to be desire to interact with page scripts using your content script. I suggest that you read the MDN page "Interacting with page scripts".

Categories

Resources