i want to click an element with a value, which will be inserted by user. I tried this:
def transition(action, value=none):
if (action=='next_page'):
button = driver.find_element_by_link_text('"value"')
button.click()
transition('next_page', value='car1')
The problem is that 'car1' value isn't inserted. What can i fix it?
What your code does, is actually calling the find_element function with the string "value", as you wrote it in quotation marks, making it a string literal
button = driver.find_element_by_link_text('"value"')
What you want to do is insert the name of the variable value without any "double" or 'single' quotation marks, like so.
button = driver.find_element_by_link_text(value)
As you are having a hard time dealing with such simple python syntax, I recommend you first learn the bare basics of the language before trying to write applications with it. There are a lot of free resources out there.
I can recommend W3Schools as a website with text and interactive examples or if you are more of the video type of learner, I can recommend the course by freeCodeCamp.org or a video series by Tech With Tim. Though the last one didn't age really well.
Related
So I'm trying to build a tool to transfer tickets that I sell. A sale comes into my POS, I do an API call for the section, row, and seat numbers ordered (as well as other information obviously). Using the section, row, and seat number, I want to plug those values into a contains (text) statement to in order to find and select the right tickets on the host site.
Here is a sample of how the tickets are laid out:
And here is a screenshot (sorry if this is inconvenient) of the DOM related to one of the rows above:
Given this, how should I structure my contains(text) statement so that it is able to find and select the correct seats? I am very new/inexperienced with automation. I messed around with it a few months ago with some success and have managed to get a tool that gets me right up to selecting the seats but the "div" path confuses me when it comes to searching for text that is tied to other text.
I tried the following structure:
for i in range(int(lowseat), int(highseat)):
web.find_element_by_xpath('//*[contains (text(), "'+section+'")]/following-sibling::[contains text(), "'+row+'")]/following-sibling::[contains text(), "'+str(i)+'")]').click()
to no avail. Can someone help me explain how to structure these statements correctly so that it searches for section, row, and seat number correctly?
Thanks!
Also, if needed, here is a screenshot with more context of the button (in cases its needed). Button is highlighted in sky blue:
you can't use text() for that because it's in nested elements. You probably want to map all these into dicts and select with filter.
Update
Here's an idea for a lazy way to do this (untested):
button = driver.execute_script('''
return [...document.querySelectorAll('button')].find(b => {
return b.innerText.match(/Section 107\b.*Row P.*Seat 10\b/)
})
''')
I have built a web crawler for a forum game in which players use specific keywords in [b] bold [/b] tags to issue their commands. The bot's job is to traverse through the thread and keep a record of all player's commands, however I'm running into a problem where if player A quotes a post from player B, the bot reads the command of player B in the quote and updates the table for player A.
I have found the specific class name of the quote box, but I cannot figure out how to remove the class from the entire post body.
I tried converting the post to text using the get_attribute('innerHTML') and successfully removed it using regex, however the code I wrote to extract the bold tags (find_attribute_by_tag_name) becomes invalid.
I have two questions for the geniuses that post here:
Is there a way I can delete a specific element from the post body? I searched throughout google and could not find a working solution
Otherwise, is there a way I can convert the HTML I get from get_attribute('innerHTML') back to an element?
def ScrapPosts( driver ):
posts=driver.find_elements_by_class_name("postdetails")
print("Total number of posts on this page:", len(posts))
for post in posts:
#print("username:",post.find_element_by_tag_name("Strong").text)
username=post.find_element_by_tag_name("Strong").text.upper()
#remove the quote boxes before sending to check command?
post_txt=post.find_element_by_class_name("content")
CheckCommand(post_txt, username)
Selenium doesn't have a built in method for deleting elements. However, you can execute some javascript code that can remove the quote box elements. See related question at: https://stackoverflow.com/a/22519967/7880461
This code will delete all elements with the class name quoteBox which I think would work for you if you just change the class name.
driver.execute_script('''
var element = document.getElementsByClassName("quoteBox"), index;
for (index = element.length - 1; index >= 0; index--) {
element[index].parentNode.removeChild(element[index]);
}
''')
Same answer- no built in way of doing that but you can use javascript. This approach would probably a lot more complicated than the first one.
This is part of my code, the id of image wont print even I use the withtag function. I think the function canvas.delete won't work is also the same problem, it seem the tag is inserted as "123","456". However, the tag I expected to use and get is 123 instead of '123'. And I guess it's the main problem I can't get the id I want with the findtag function.
CurrentImage=Note[NoteIndexLocal]
Temp=canvas.create_image(XShow,YShow,image=CurrentImage,tag=123)
print canvas.find_withtag(123) #This Wont Work,printed()
canvas.delete(123) #This Wont Work
print canvas.gettags(Temp) #printed '123'
From: http://effbot.org/tkinterbook/canvas.htm
Tags are symbolic names attached to items. Tags are ordinary strings,
and they can contain anything except whitespace (as long as they don’t
look like item handles).
Use str(123) instead of 123
EDIT: correct answer is in text from doc "as long as they don’t look like item handles". Number 123 looks like item handle (print Temp to see how it looks like) so it doesn't work. Use text like "a123" and it will work.
Motivation: I was going around assigning parameters read in from a config file to variables in a function like so:
john = my_quest
terry = my_fav_color
eric = airspeed
ni = swallow_type
...
when I realized this was going to be a lot of parameters to pass. I thus decided I'd put these parameters in a nice dictionary, grail, e.g. grail['my_quest'] so that the only thing I needed to pass to the function was grail.
Question: Is there a simple way in Sublime (or Notepad++, Spyder, Pycharm, etc.) to paste grails['variable'] around those variables in one step, instead of needing to paste the front and back seperately? (I know about multiple cursors in Sublime, that does help, but I'd love to find a "highlight-variable-and-hit-ctrl-meta-shift-\" and it's done.)
Based on examples you provided, this is a simple task solvable using standard regex find/replace.
So in Notepad++, record this macro (for recording control examine Macro menu):
Press Ctrl+H to open Find/Replace dialog
Find what: = (.*)$
Replace with: = grail['\1']
Choose Regular Expression and press Replace All
If you finish recording the macro and you choose to save it, shortcut key is requested. Assign your favorite ctrl-meta-shift-\ and you are done.
I am trying to migrate a forum to phpbb3 with python/xpath. Although I am pretty new to python and xpath, it is going well. However, I need help with an error.
(The source file has been downloaded and processed with tagsoup.)
Firefox/Firebug show xpath: /html/body/table[5]/tbody/tr[position()>1]/td/a[3]/b
(in my script without tbody)
Here is an abbreviated version of my code:
forumfile="morethread-alte-korken-fruchtweinkeller-89069-6046822-0.html"
XPOSTS = "/html/body/table[5]/tr[position()>1]"
t = etree.parse(forumfile)
allposts = t.xpath(XPOSTS)
XUSER = "td[1]/a[3]/b"
XREG = "td/span"
XTIME = "td[2]/table/tr/td[1]/span"
XTEXT = "td[2]/p"
XSIG = "td[2]/i"
XAVAT = "td/img[last()]"
XPOSTITEL = "/html/body/table[3]/tr/td/table/tr/td/div/h3"
XSUBF = "/html/body/table[3]/tr/td/table/tr/td/div/strong[position()=1]"
for p in allposts:
unreg=0
username = None
username = p.find(XUSER).text #this is where it goes haywire
When the loop hits user "tompson" / position()=11 at the end of the file, I get
AttributeError: 'NoneType' object has no attribute 'text'
I've tried a lot of try except else finallys, but they weren't helpful.
I am getting much more information later in the script such as date of post, date of user registry, the url and attributes of the avatar, the content of the post...
The script works for hundreds of other files/sites of this forum.
This is no encode/decode problem. And it is not "limited" to the XUSER part. I tried to "hardcode" the username, then the date of registry will fail. If I skip those, the text of the post (code see below) will fail...
#text of getpost
text = etree.tostring(p.find(XTEXT),pretty_print=True)
Now, this whole error would make sense if my xpath would be wrong. However, all the other files and the first numbers of users in this file work. it is only this "one" at position()=11
Is position() uncapable of going >10 ? I don't think so?
Am I missing something?
Question answered!
I have found the answer...
I must have been very tired when I tried to fix it and came here to ask for help. I did not see something quite obvious...
The way I posted my problem, it was not visible either.
the HTML I downloaded and processed with tagsoup had an additional tag at position 11... this was not visible on the website and screwed with my xpath
(It probably is crappy html generated by the forum in combination with tagsoups attempt to make it parseable)
out of >20000 files less than 20 are afflicted, this one here just happened to be the first...
additionally sometimes the information is in table[4], other times in table[5]. I did account for this and wrote a function that will determine the correct table. Although I tested the function a LOT and thought it working correctly (hence did not inlcude it above), it did not.
So I made a better xpath:
'/html/body/table[tr/td[#width="20%"]]/tr[position()>1]'
and, although this is not related, I ran into another problem with unxpected encoding in the html file (not utf-8) which was fixed by adding:
parser = etree.XMLParser(encoding='ISO-8859-15')
t = etree.parse(forumfile, parser)
I am now confident that after adjusting for strange additional and multiple , and tags my code will work on all files...
Still I will be looking into lxml.html, as I mentioned in the comment, I have never used it before, but if it is more robust and may allow for using the files without tagsoup, it might be a better fit and save me extensive try/except statements and loops to fix the few files screwing with my current script...