Issue
I present to you some executable, functionable and GUI code, created for study purposes only.
I have a problem with automatic clicks after except, precisely, after the exception ElementClickInterceptedException
, I would like to continue the automatic clicks code in a While Loop, but always RESPECTING the set number of buttons to click (limit
). The problem is that not all buttons set are clicked since I get the exception. Basically if I set 20 clicks with limit, the script seems to work fine until I get the exception. After the exception the script still continues to click on some buttons, but not on 20. I can't understand what the problem is. There can be various reasons. This is the part that is troubling me (below is the complete code):
limit = int(number_requests.get())
i = 1
x = 1
while i <= limit:
i = i + 1
try:
#These are the staves of the button list, useful for scrolling down. Each staff is a button
row = wait.until(EC.visibility_of_element_located((By.XPATH, f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])[{i}]")))
#click on button
add = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Add Friend']"))).click()
#vertical scroll down
driver.execute_script("arguments[0].scrollIntoView(true);", row)
time.sleep(delay)
except ElementClickInterceptedException:
print("This button could not be clicked")
close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()
while True:
x = x + 2
row_skip = wait.until(EC.visibility_of_element_located((By.XPATH, f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])[{x}]")))
addd_skip = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Add Friend']"))).click()
break
NOTE: you will be wondering what is the xpath in "row"?. Below, going down here, I explain what is the xpath in "row" and show the screenshot
WHAT DOES MY CODE DO? The code I am showing you almost everything works fine, but there is something wrong. It works like this:
- Automatically click on each button (setting the delay and the number of buttons to click)
- As you click on the buttons, the list of buttons scrolls down with the vertical scrollbar
- When I get the
ElementClickInterceptedException
error, the popup closes automatically (click "ok" to close) - Return to the list of buttons and skip a button (1, one only)
- I continue the While loop code (including
limit
), then I keep clicking on each button and if I get the ElementClickInterceptedException error it returns to point 3, 4 and 5.
My code works fine at first, then there are problems, although I don't understand which one exactly.
WHAT DO I WANT TO GET? The purpose of the code is to skip a button (1, only one) when I get an ElementClickInterceptedException and keep clicking on the other buttons after the RESPECT exception of the number set in limit. Why do I want to skip a button in the exception with the second While?
PROBLEM: If i set 20 buttons to click, they don't actually click 20 buttons, but they don't actually click, for example only 11 or 12 buttons. Also it seems that we have problems in the vertical scrollbar (even if my code looks correct) because the scrollbar drops down just a little, then stops, so it doesn't display any other buttons.
My idea is that the problem could be one of these: either there is a problem with the scroll bar scrolling (it scrolls down only a little, then stops), or "limit" is entered in the wrong place or in wrong way, or when I get the exception it creates a problem in the "try" code (I also tried with finally, but without solution), or I don't know what other problem it could be
ATTENTION, VERY IMPORTANT: WHY SECOND LOOP WHILE IN THE EXCEPTION? When the popup closes, the script will continue to click the buttons, but the last button it got to with the exception will change its name from "Cancel Request" to "Add Friend". Consequently, the script will continue to click endlessly on the same button, because the popup will open, then the popup will close, then the button will change its name, it will be clicked and the popup will open again.
How can I solve? Code complete is:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from time import sleep
import time
import tkinter as tk
from tkinter import ttk
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
import os
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.common.exceptions import ElementClickInterceptedException
root = tk.Tk()
root.title("...")
root.geometry('530x500')
root.configure(bg='white')
topbar = tk.Frame(root, bg='#3b589e', height=42, width = 660)
topbar.place(x=1, y=1)
secondbar = tk.Frame(root, bg='#f0f2f5', height=42, width = 660)
secondbar.place(x=1, y=40)
#GUI
label_email = Label(root, text="email", bg='#3b589e', foreground="white")
label_email.place(x=2, y=10)
email = tk.Entry(root)
email.place(x=50, y = 9)
label_password = Label(root, text="password", bg='#3b589e', foreground="white")
label_password.place(x=260, y = 10)
password = tk.Entry(root)
password.place(x=335, y = 9)
link_label = Label(root, text="Post Link", bg='#f0f2f5', foreground="black")
link_label.place(x=2, y = 52)
link = tk.Entry(root, width = 50)
link.place(x=97, y = 50)
link.insert(tk.END, "https://www.facebook.com/FranzKafkaAuthor/posts/4221775217885172")
number_requests_label = Label(root, text="How many requests to send?", bg='white', foreground="black")
number_requests_label.place(x=2, y = 110)
number_requests = tk.Entry(root)
number_requests.place(x=4, y = 130)
number_requests.insert(tk.END, "20")
time_label = Label(root, text="Seconds between requests?", bg='white', foreground="black")
time_label.place(x=2, y = 180)
time_requests = tk.Entry(root)
time_requests.place(x=4, y = 200)
time_requests.insert(tk.END, "1")
email.insert(tk.END, "[email protected]")
password.insert(tk.END, "example password")
def start_with_limits():
# get the values from the textboxes and convert them to integers
delay = int(time_requests.get())
limit = int(number_requests.get())
#Access Facebook
profile_path = '/usr/bin/firefox/firefox'
options=Options()
options.set_preference('profile', profile_path)
options.set_preference('network.proxy.type', 4)
options.set_preference('network.proxy.socks', '127.0.0.1')
options.set_preference('network.proxy.socks_port', 9050)
options.set_preference("network.proxy.socks_remote_dns", False)
service = Service('/home/xxxx/bin/geckodriver')
driver = Firefox(service=service, options=options)
driver.set_window_size(600, 990)
driver.set_window_position(1, 1)
driver.get("http://www.facebook.com")
#Cookies before login
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-cookiebanner="accept_button"]'))).click()
#Login
username_box = driver.find_element(By.ID, 'email')
username_box.send_keys(email.get())
password_box = driver.find_element(By.ID, 'pass')
password_box.send_keys(password.get())
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '/html/body/div[1]/div[2]/div[1]/div/div/div/div[2]/div/div[1]/form/div[2]/button'))).click()
# --OPTIONAL
#Cookies before login (Sometimes it is required while sometimes not
#WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[aria-label='Allow all cookies'] span span"))).click()
#Open link
driver.get(link.get())
#Click on icon-like
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[@class='j1lvzwm4']"))).click()
time.sleep(1)
#Click su ALL
WebDriverWait(driver, 2000).until(EC.element_to_be_clickable((By.XPATH, '/html/body/div[1]/div/div[1]/div/div[4]/div/div/div[1]/div/div[2]/div/div/div/div[1]/div/div/div/div/div[2]/div[2]'))).click()
time.sleep(1)
#Scroll down and press "Add friend" buttons
wait = WebDriverWait(driver, 30)
i = 1
x = 1
while i <= limit:
i = i + 1
try:
row = wait.until(EC.visibility_of_element_located((By.XPATH, f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])[{i}]")))
add = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Add Friend']"))).click()
driver.execute_script("arguments[0].scrollIntoView(true);", row)
time.sleep(delay)
except ElementClickInterceptedException:
print("This button could not be clicked")
close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()
while True:
x = x + 2
row_skip = wait.until(EC.visibility_of_element_located((By.XPATH, f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])[{x}]")))
addd_skip = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Add Friend']"))).click()
break
begin = Button(root, text="Start", bg='#3b589e', foreground='white', width=7, command= start_with_limits)
begin.place(x=1, y=420)
root.mainloop()
ADD INFORMATION: "i" has the main purpose of not skipping any staff, so it must scroll and count each staff (all staves). While "x", compared to "i", must skip 1 button (1 only), but it must skip it 1 time, then skip 1 button only 1 time. Subsequently, after the exception has jumped a button with "x", then it returns to the first While that clicks on all the buttons (not jumping any) until a new exception is found.
XPATH IN ROW? With the xpath in "row", I am selecting every single row where there is a button. The names of the row are all called the same. To be precise, on your screen, you have to click on the blue like icon and then click on "All". I am selecting every single staff of that section. P.S: (do not notice that my browser uses another language, obviously I will do the tests with another browser from the English language)
P.S: I would like to point out that my question is for personal and informational study purposes only. I am new to Python and am now learning Selenium. I don't want to use spam and don't really want to use the script in real cases. Respect for Facebook rules. As I said, my question is just a curiosity for reasons of personal study to understand the code of this curiosity of mine.
Solution
You are trying to send a given number of requests and skip bad requests in a overly complicated way. This is likely the simplest way to do it:
- check if an user has the “Add Friend” button
- if yes, click the button
- if the error box appears, close it, otherwise increment by 1 the number of sent requests
- if yes, click the button
- if the desired number of requests were sent, stop, otherwise go to the next user
.
requests_to_send = 20
requests_sent = 0
requests_failed = 0
i = 0 # number of users checked
users = []
while requests_sent < requests_to_send:
# if necessary, wait until new users are loaded
while i >= len(users):
users = driver.find_elements(By.CSS_SELECTOR, 'div[aria-label=Reactions] div:nth-child(3) div[data-visualcompletion=ignore-dynamic]')
time.sleep(.5)
driver.execute_script('arguments[0].scrollIntoView({block: "center"});', users[i])
button = users[i].find_elements(By.CSS_SELECTOR, 'div[aria-label="Add Friend"]')
if button:
button[0].click()
time.sleep(2)
cant_send = driver.find_elements(By.CSS_SELECTOR, 'div[aria-label=OK]')
if cant_send:
requests_failed += 1
cant_send[0].click()
# wait until popup is closed
while driver.find_elements(By.CSS_SELECTOR, 'div[aria-label=OK]'):
time.sleep(.5)
else:
requests_sent += 1
i += 1
print(f'users checked {i} - req. sent {requests_sent} - req. failed {requests_failed}', end='\r')
p.s. fanne buono uso!
Answered By - sound wave
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.