0

I am looking for a way to shorten my code.

I am gathering captcha values from https://www.ultimateqa.com/complicated-page/ and submitting them for 3 captcha boxes.

Can I shorten my code using a function? Or should I use different css selectors?

for i in range(1):
    cap0 = '#et_pb_contact_form_0 > div.et_pb_contact > form > div > div > p > input'
    captext1= driver.find_element_by_css_selector(cap0).get_attribute("data-first_digit")
    capnumb1 = int(captext1)
    captext2= driver.find_element_by_css_selector(cap0).get_attribute("data-second_digit")
    capnumb2 = int(captext2)
    driver.find_element_by_css_selector(cap0).send_keys(capnumb1 + capnumb2)
for i in range(1):
    cap1 = '#et_pb_contact_form_1 > div.et_pb_contact > form > div > div > p > input'
    captext1= driver.find_element_by_css_selector(cap1).get_attribute("data-first_digit")
    capnumb1 = int(captext1)
    captext2= driver.find_element_by_css_selector(cap1).get_attribute("data-second_digit")
    capnumb2 = int(captext2)
    driver.find_element_by_css_selector(cap1).send_keys(capnumb1 + capnumb2)
for i in range(1):
    cap2 = '#et_pb_contact_form_2 > div.et_pb_contact > form > div > div > p > input'
    captext1= driver.find_element_by_css_selector(cap2).get_attribute("data-first_digit")
    capnumb1 = int(captext1)
    captext2= driver.find_element_by_css_selector(cap2).get_attribute("data-second_digit")
    capnumb2 = int(captext2)
    driver.find_element_by_css_selector(cap2).send_keys(capnumb1 + capnumb2)

3 Answers 3

2

You can use selector that matches all 3 cases (just separate CSS selectors with comma) and handle them in a loop:

cap_css = '#et_pb_contact_form_0 > div.et_pb_contact > form > div > div > p > input, #et_pb_contact_form_1 > div.et_pb_contact > form > div > div > p > input, #et_pb_contact_form_2 > div.et_pb_contact > form > div > div > p > input'
cap_list = driver.find_elements_by_css_selector(cap_css)
for cap in cap_list:
    captext1= cap.get_attribute("data-first_digit")
    capnumb1 = int(captext1)
    captext2= cap.get_attribute("data-second_digit")
    capnumb2 = int(captext2)
    cap.send_keys(capnumb1 + capnumb2)

P.S. for i in range(1) loop should be removed as it doesn't make any sense

Sign up to request clarification or add additional context in comments.

1 Comment

Good to know! that makes things alot easier, thanks :)
2

Few pythonic/programmatic notes:

  • A for loop with range(1) is iterating once (on the 0th element); thus, not very useful as regular code iterates once anyways.
  • Anytime you see similar code being written down, you can generally abstract the logic into reusable code.

I'm personally unfamiliar with selenium and not that great with CSS, but here's a go at the python:

def get_digit(cap,attr):
    element = driver.find_element_by_css_selector(cap).get_attribute(attr)
    return (element, int(element))

caps = ['#et_pb_contact_form_0', '#et_pb_contact_form_1', '#et_pb_contact_form_2']
cap_end = ' > div.et_pb_contact > form > div > div > p > input'
for cap in caps:
    tmp_cap = cap + cap_end
    captext1, capnumb1 = get_digit(tmp_cap, "data-first_digit")
    captext2, capnumb2 = get_digit(tmp_cap, "data-second_digit")
    driver.find_element_by_css_selector(tmp_cap).send_keys(capnumb1 + capnumb2)

Let me know in a comment if this works for you!

Using my function with JaSON's combined CSS selectors logic:

def get_digit(cap,attr):
    element = driver.find_element_by_css_selector(cap).get_attribute(attr)
    return (element, int(element))

cap_css = '#et_pb_contact_form_0 > div.et_pb_contact > form > div > div > p > input, #et_pb_contact_form_1 > div.et_pb_contact > form > div > div > p > input, #et_pb_contact_form_2 > div.et_pb_contact > form > div > div > p > input'
cap_list = driver.find_elements_by_css_selector(cap_css)
for cap in cap_list:
    captext1, capnumb1 = get_digit(cap, "data-first_digit")
    captext2, capnumb2 = get_digit(cap, "data-second_digit")
    cap.send_keys(capnumb1 + capnumb2)

1 Comment

Glad to hear it! I have no knowledge of Selenium haha... Also, I updated my answer to include a merge of JaSON's answer and mine own. That should also work assuming the combined selector is valid.
-1

You can use the name attribute with the loop index as parameter

for i in range(3):
    cap = driver.find_element_by_css_selector(f'[name="et_pb_contact_captcha_{i}"]')
    captext = cap.get_attribute("data-first_digit")
    capnumb1 = int(captext)
    captext = cap.get_attribute("data-second_digit")
    capnumb2 = int(captext)
    cap.send_keys(capnumb + capnumb2)

Or locate all the captcha by partial name and iterate over the list

captchas = driver.find_elements_by_css_selector('[name^="et_pb_contact_captcha_"]')

for cap in captchas:
    captext = cap.get_attribute("data-first_digit")
    capnumb1 = int(captext)
    captext = cap.get_attribute("data-second_digit")
    capnumb2 = int(captext)
    cap.send_keys(capnumb + capnumb2)

No need to relocate the captcha field every time, locate it once and use it.

1 Comment

That is another great solution. I am learning alot, thanks :p

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.