Find element with Selenium - python

I need to find class="a-icon a-icon-addon couponBadge" on Amazon page, like this.
If the class exist, i need to set variable x == 0, if it doesn't exist, i need to set variable x == 1.
I tried this code, but it doesn't work. How can i check this?
try:
couponBadge = driver.find_elements_by_class_name("a-icon a-icon-addon couponBadge")
if couponBadge != None:
x == 0
else:
x == 1
except AttributeError:
print("error")

Please try this:
couponBadge = driver.find_elements_by_class_name("a-icon a-icon-addon couponBadge")
if couponBadge:
x = 0
else:
x = 1
driver.find_elements_by_class_name returns a list.
In case there are elements matching this locator the list will be non-empty, so it will be interpreted as a Boolean True. Otherwise it will be interpreted as False.
Also to assign a value to variable you should use a single =, not ==.
== is used for comparison.
Also, as mentioned by CrunchyBox you should rather use find_element_by_css_selector, not get_elements_by_class_name.

You need to use a single equals sign, not two, to assign to a variable.
e.g. x = 1
It also looks like Selenium's get_elements_by_class_name function only supports inputting a single class name, not multiple as is shown in your example, so you might want to look into driver.find_element_by_css_selector().
e.g. driver.find_element_by_css_selector('.a-icon.a-icon-addon.couponBadge')

Related

Python: Using bool() to select which vars are TRUE, then use those values to call function

First question ever! I've built a GUI which asks user to input 2 of possible 5 values. Each pair of values (10 possible pairs) get used to run 10 different solution functions named Case_n to which all five values (both zero and non-zero) are passed.
The problem I'm having is getting the bool() results stripped down to 2 digit without brackets, etc and then placed into a variable used to create the name of the function to call.
I've run the logic, with TRUE values added to a list, then converted the list to a string so I could strip it down to just the numerals, saved the 2 digit string and added it to the Case_n name. Now, when I try to use the name to call the function, I get an error that a string is not callable. Please help . . .
s = 5 #vars. For this example, I've pre-loaded 2 of them
a = 15
l = 0
r = 0
e_deg = 0
ve = 0
case = []
if bool(s):
case.append(1)
if bool(a):
case.append(2)
if bool(l):
case.append(3)
if bool(r):
case.append(4)
if bool(e_deg):
case.append(5)
nm = str(case) # placeholder to convert case to string
case_num = nm[1] + nm[4] # this returns 12 as a string
# create case_num var, using the string
Case = "Case_" + case_num
print("Case = ",Case) # Should be Case_12
def Case_12(s,a,l,r,e_deg,ve):
print("Case_12 running")
Case(s,a,l,r,e_deg,ve) ```
You could just use eval(Case) but I advise against it as you are processing user input and it could be a security risk.
An easy way would be to build the following dict :
my_dict = {"Case_1": Case_1, ..., "Case_12" : Case_12}
And then, instead of calling Case, you would do
my_dict[Case](s,a,l,r,e_deg,ve)
You could also create a function :
def choose_case(my_case_as_str):
my_case_dict = {"Case_1": Case_1, ..., "Case_12": Case_12}
return my_case_dict[my_case_as_str]
And then call
choose_case(Case)(s,a,l,r,e_deg,ve)
By the way, you probably don't want your function and variable names to start with an uppercase letter. You also probably want to use a safer way to get user input (for example use Template str)

Error when trying to build logical parser

So i have these strings stored in database and i want to convert them to python expression to use them with if statement. I will store these strings into list and will loop over them.
For example:
string = "#apple and #banana or #grapes"
i am able to convert this string by replacing # with "a==" and # with "b==" to this :
if a == apple and b == banana or b == grapes
hash refers to a
# refers to b
But when i use eval it throws up error "apple is not defined" because apple is not in quotes. so what i want is this:
if a == "apple" and b == "banana" or b == "grapes"
Is there any way i can do this ?
The strings stored in DB can have any type of format, can have multiple and/or conditions.
Few examples:
string[0] = "#apple and #banana or #grapes"
string[1] = "#apple or #banana and #grapes"
string[2] = "#apple and #banana and #grapes"
There will be else condition where no condition is fullfilled
Thanks
If I understand correctly you are trying so setup something of a logical parser - you want to evaluate if the expression can possibly be true, or not.
#word or #otherword
is always true since it's possible to satisfy this with #=word for example, but
#word and #otherword
is not since it is impossible to satisfy this. The way you were going is using Python's builtin interpreter, but you seem to "make up" variables a and b, which do not exist. Just to give you a starter for such a parser, here is one bad implementation:
from itertools import product
def test(string):
var_dict = {}
word_dict = {}
cur_var = ord('a')
expression = []
for i,w in enumerate(string.split()):
if not i%2:
if w[0] not in var_dict:
var_dict[w[0]] = chr(cur_var)
word_dict[var_dict[w[0]]] = []
cur_var += 1
word_dict[var_dict[w[0]]].append(w[1:])
expression.append('{}=="{}"'.format(var_dict[w[0]],w[1:]))
else: expression.append(w)
expression = ' '.join(expression)
result = {}
for combination in product(
*([(v,w) for w in word_dict[v]] for v in word_dict)):
exec(';'.join('{}="{}"'.format(v,w) for v,w in combination)+';value='+expression,globals(),result)
if result['value']: return True
return False
Beyond not checking if the string is valid, this is not great, but a place to start grasping what you're after.
What this does is create your expression in the first loop, while saving a hash mapping the first characters of words (w[0]) to variables named from a to z (if you want more you need to do better than cur_var+=1). It also maps each such variable to all the words it was assigned to in the original expression (word_dict).
The second loop runs a pretty bad algorithm - product will give all the possible paring of variable and matching word, and I iterate each combination and assign our fake variables the words in an exec command. There are plenty of reasons to avoid exec, but this is easiest for setting the variables. If I found a combination that satisfies the expression, I return True, otherwise False. You cannot use eval if you want to assign stuff (or for if,for,while etc.).
Not this can drastically be improved on by writing your own logical parser to read the string, though it will probably be longer.
#Evaluted as (#apple and #banana) or #grapes) by Python - only #=apple #=banana satisfies this.
>>> test("#apple and #banana or #grapes")
True
#Evaluted as #apple or (#banana and #grapes) by Python - all combinations satisfy this as # does not matter.
>>> test("#apple or #banana and #grapes")
True
#demands both #=banana and #=grapes - impossible.
>>> test("#apple and #banana and #grapes")
False
I am not sure of what you are asking here, but you can use the replace and split functions :
string = "#apple and #banana"
fruits = string.replace("#", "").split("and")
if a == fruits[0] and b == fruits[1]:
Hope this helps

Better / More pythonic way to process the results of a function with multiple return values

The code below works, but looks very ugly. I'm looking for a more pythonic way to write the same thing.
The goal:
React on a result of a function that returns multiple values.
Example function
def myfilterfunc(mystr):
if 'la' in mystr:
return True, mystr
return False, None
This returns True and a string (if the string cointains "la"), or False and nothing.
In a second function, I'm passing myfilterfunc as an optional parameter
def mymainfunc(mystr,filterfunc=None):
This function fills a returnlist.
If no function is given, the result is not filtered and added as is.
If a filter function is given, if the filter function returns
True, a returned string is added. (This is just an example that would
easily work with one return value, but I'm trying to get the systax
right for a more complicated setup)
if filterfunc:
tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
if tmp_status:
returnlist.append(tmp_string)
else:
returnlist.append(mystr[startpos:nextitem])
Any idea how I can write this without using temporary variables to store the return values of the function?
Full "working" test code below
def string2list(mystr,splitlist,filterfunc=None):
returnlist = []
startpos = 0
nextitem = -1
matched = True
while matched:
matched = False
for sub in splitlist:
if startpos == 0:
tmpi = mystr.find(sub)
else:
tmpi = mystr.find(sub,startpos + 1)
if (tmpi > 0) and ((nextitem < 0) or (nextitem > tmpi)):
nextitem = tmpi
matched = True
if filterfunc:
tmp_status,tmp_string = filterfunc(mystr[startpos:nextitem])
if tmp_status:
returnlist.append(tmp_string)
else:
returnlist.append(mystr[startpos:nextitem])
startpos = nextitem
nextitem = -1
return returnlist
def myfilterfunc(mystr):
if 'la' in mystr:
return True,mystr
return False,''
splitlist = ['li','la']
mytext = '''
li1
li2
li3
fg4
fg5
fg6
la7
la
la
tz
tz
tzt
tz
end
'''
print string2list(mytext,splitlist)
print
print string2list(mytext,splitlist,myfilterfunc)
If this is going to happen often you can factor out the uglyness:
def filtered(f, x):
if f:
status, result = f(x)
return result if status else x
else:
return x
used like
returnlist.append(filtered(filterfunc, mystr[startpos:nextitem]))
so that if you have many similar optional filters the code remains readable. This works because in Python functions/closures are first class citizens and you can pass them around like other values.
But then if the logic is about always adding (either the filtered or the unfiltered) why not just write the filter to return the input instead of (False, "") in case of failure?
That would make the code simpler to understand...
returnlist.append(filterfunc(mystr[startpos:nextitem]))
I think there are two better approaches to your problem that don't involve using two return values.
The first is to simply return a Boolean value and not a string at all. This works if your filter is always going to return the string it was passed unmodified if it returns a string at all (e.g. if the first value is True). This approach will let you avoid using temporary values at all:
if filterfunc:
if filterfunc(mystr[startpos:nextitem]):
returnlist.append(mystr[startpos:nextitem])
(Note, I'd suggest renaming filterfunc to predicate if you go this route.)
The other option will work if some filterfunc might return a different second value than it was passed under some situations, but never the 2-tuple True, None. In this approach you simply use the single value as both the signal and the payload. If it's None, you ignore it. If it's anything else, you use it. This does require a temporary variable, but only one (and it's a lot less ugly).
if filterfunc:
result = filterfunc(mystr[startpos:nextitem])
if result is not None:
returnlist.append(result)

Compare Two Lists and Create a List

I'm still trying to learn programming so please help me simplify this. I'm trying to run something that looks through the indices in my list and if it finds a 1 returns "yay" (just for debugging purposes). Here's what I have so far:
def replaceValues(distList, indexList):
for i in range (1,len(indexList)):
if indexList[i] = 1
return "yay!"
However, I get a syntax error whenever I run this, which underlines the 1. Please help!
Thanks!
Apart from incorrect indentation(fixed below), you are using = when you should be using ==, and you left out a colon from your if statement.
= is used to assign values
== evaluates equality(returning a boolean i.e True or False)
You left out a : in your if statement.
Corrected code:
def replaceValues(distList, indexList):
for i in range (1,len(indexList)):
if indexList[i] == 1:
return "yay!"
If you don't understand exactly how Python uses whitespace/indentation as an integral part of it's syntax/structure and other syntax basics, then you need to get on that i.e tutorials.. A quick google should turn up many. I recommend Udacity or Codeacademy
There are three syntax errors that I see.
First, you're using the = sign (assignment) when you need == (comparison).
Second, you're missing a colon at the end of your if statement.
Finally, you must* have an indented block after your if statement.
All together, it should read like this:
if indexList[i] == 1: # double-equals and colon
return "yay!" # This must be indented to the proper level
You should really go have a look at the tutorials; this is all stuff that's laid out very well there, and it's all critical to doing pretty much anything in Python.
*Technically, you can also follow an if statement with an expression on the same line (e.g. if 1: pass). However, I personally think this is hideous in almost every case.
= is an assignment statement. Example:
name = "tyler"
You should use == to check for equality of primitives (you're comparing integers, which are primitives).
Switch :
if indexList[i] = 1
to:
if indexList[i] == 1
Try it like this:
def replaceValues(distList, indexList):
for k in range(1, len(indexList)):
if indexList[k] == 1:
return "yay!"

how to set the value of len(list_name)...?

I have a list that might return null values, then I have to iterate through it...ex:
for iter_aeh in range(len(alert_event_history_rows)):
alert_event_history_rows is a list and it can be null, so I want to set len(alert_event_history_rows) = 1 if alert_event_history_rows is a list of null values(0 rows).
But I get following error:
SyntaxError: can't assign to function call
for record_ae in alert_event_rows:
if len(alert_event_history_rows) == 0:
len(alert_event_history_rows) = 1
for iter_aeh in range(len(alert_event_history_rows)):
How to set the value of len(alert_event_history_rows)...?
Don't. Just handle the case where your list is empty with logic:
if alert_event_history_rows:
for item in alert_event_history_rows:
# do something
else:
# alert_event_history_rows was an empty list..
# do something else
This is a syntax error indeed:
len(alert_event_history_rows) = 1
... because you cannot make an assignment to a function call on the left hand side. It must be a variable that can receive the value. If what you really want to do is reinitialize that list to a single element null list, then you might do:
alert_event_history_rows = [None]
This should fix your problem
for record_ae in alert_event_rows:
for iter_aeh in range(max(len(alert_event_history_rows), 1)):

Categories