在用Selenium打开弹出窗口时,请跳过时循环中单击一个元素。循环时问题

发布于 2025-01-23 09:46:34 字数 9231 浏览 1 评论 0 原文

此循环滚动浏览网页上名称列表,然后单击名称旁边的每个“添加”按钮。它运行良好且正确地

wait = WebDriverWait(driver, 30)
i = 1

while i <= limit:
    i = i + 1

    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']"))).click()
    
    driver.execute_script("arguments[0].scrollIntoView(true);", row, add)
 

有些按钮会产生问题,因为如果我单击它们,我会收到一个错误弹出窗口,他说我不能将该人添加到朋友中。因此,要解决我创建此 colled_popup = webdriverwait(driver,20).until(ec.element_to_be_be_clickable(((by.xpath,“ // span [text()text()='ok']))。 自动单击“确定”并关闭弹出窗口。此代码效果很好,可以正确单击“确定”按钮,然后正确关闭弹出窗口。有关向读者的信息,如果我不使用“ close_popup”,我会得到错误 element clickInterpectedError

问题的描述: 问题是弹出窗口关闭时,因为按钮从“取消请求”更改为“添加朋友”,您将再次单击(无限期地)后者“添加朋友”,我无法添加。弹出窗口关闭时,循环将始终单击相同的“添加”按钮(例如John,给出错误并打开弹出窗口的按钮),而无需前进,并且永远不会继续单击其他按钮。 重要:发生这种情况是因为某个“添加朋友”按钮(例如John),当我单击它时,将其更改为“取消请求”,并且弹出窗口将打开。因此,当我在弹出窗口上单击“确定”并关闭时,“取消请求”按钮将返回“添加朋友”。

因此,脚本将正常继续,每个“添加朋友”按钮都会点击,包括我无法添加的约翰,打开弹出窗口。

“在此处输入图像说明”

因此,我将无限期地按以下顺序获取这些操作:

  1. 单击“添加”按钮
  2. 打开弹出窗口
  3. 关闭弹出窗口,这要归功于单击“确定”的代码
  4. 再次单击“添加”按钮,因为当我关闭弹出窗口时,按钮将从“取消请求”更改为“添加”的名称,
  5. 从无限开始上面的1到4

我想跳过单击“添加朋友”按钮,该按钮阻止了循环(在其上或其他连续的循环上)并打开弹出窗口。

确切地说,如果弹出窗口打开,那么当弹出窗口关闭并返回人们的名字列表时,我想恢复单击“添加朋友”按钮,但要跳过一个按钮(只有1个,只有一个按钮这将打开弹出窗口并阻止循环),然后恢复单击第一个的所有“添加frriend”按钮,而 又不跳过(除非弹出窗口发生相同的问题)。

因此,第一个执行第一个时,然后执行第一个段(跳过一个按钮),然后返回到第一个,而该量将继续单击后续按钮(跳过按钮之后)。第二个期限的目的是在不按“添加“朋友”按钮”按钮时调用它,因此其目的是跳过“添加朋友”按钮,然后恢复单击后续按钮(跳过按钮后)。这是我的想法,但是我不确定我在代码良好的情况下写了第二本书,

但我尝试添加尝试和上述代码外。这个例外是(我接近解决方案,但有问题):

except ElementClickInterceptedException:
    print("A button cannot be pressed. You go to the next button ...")

    close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()

    #I skip a button, add only one (1) friend, then stop, and it's back to the main loop for to add and click on all friends
    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
            

我想到了这个解决方案,但是我不知道它是否正确。我曾认为,当我获得该弹出窗口时,它可以暂时开始增量2以跳过按钮。之后,我们关闭2的增量,然后循环时,然后我们返回主循环。也许另一个解决方案是,如果单击相同的按钮两次,那么您必须跳过它

如何解决问题?您能建议一个代码答案吗?谢谢,

这是完整且可执行的代码(包括GUI),以防任何人都想测试和帮助我。 我不想垃圾邮件问题,因此我创建了可能选择5个人将请求发送到的可能性。该脚本仅用于我自己的学习目的:

    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
    
    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/3985338151528881") #example link
    
    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, "5")
    
    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)
    
    
    def start_with_limits(): 
        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') ########### CHANGE YOUR PATH
        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

        try:
    
            while i <= limit:
                i = i + 1
    
                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, add)
                time.sleep(delay)
    
                #code for close popup
                #close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()
    
    
        except ElementClickInterceptedException:
            print("A button cannot be pressed. You go to the next button ...")

            close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()

            #I skip a button, add only one (1) friend, then stop, and it's back to the main loop for to add and click on all friends
            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()

This loop scrolls through the list of names on a web page and clicks on each "Add" button next to the name. It works well and correctly

wait = WebDriverWait(driver, 30)
i = 1

while i <= limit:
    i = i + 1

    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']"))).click()
    
    driver.execute_script("arguments[0].scrollIntoView(true);", row, add)
 

Some buttons create problems, because if I click on them I get an error popup who says I can't add that person to friends. So to solve i created this close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click() to automatically click "Ok" and close the popup. This code works well and correctly, click correctly on the "Ok" button and close the popup correctly. For information to the reader, if I don't use "close_popup", I get the error ElementClickInterceptedError
enter image description here

DESCRIPTION OF THE PROBLEM:
The problem is when the popup closes,because the button changes from "Cancel Request" to "Add Friend" and you will click again (indefinitely) the latter "Add Friend" which I cannot add. When the popup closes, the loop will always click on the same "Add" button (for example John, the button that gives an error and opens the popup) without ever going forward and never continuing to click on the other buttons. IMPORTANT: This happens because a certain "Add Friend" button (for example John only), when I click on it, changes to "Cancel Request" and the popup opens. So when I click "Ok" on the popup and it closes, then the "Cancel Request" button will return to "Add Friend".

Consequently the script will continue normally and every "Add Friend" button will be clicked, including John's that I can't add and that opens the popup.

enter image description here

Consequently, I will indefinitely obtain these operations in the following order:

  1. Click on the "Add" button
  2. Opening the popup
  3. Closing the popup, thanks to the code that clicks on "Ok"
  4. Click on the "Add" button again, because when I close the popup the button will change name from "Cancel Request" to "Add"
  5. Beginning at infinity of points 1 to 4 above

I would like to skip the click on the "Add Friend" button that blocks the loop (on it or on other successive ones) and opens the popup.

Precisely I would like that if the popup opens, then when the popup closes and returns to the list of people's names, I would like to resume clicking on the "Add Friend" buttons BUT by skipping a single button (1 only, only the one that opens the popup and blocks the loop) and then resuming clicking all the "Add Frriend" buttons again of the first While, without skipping any more (unless the same problem occurs with a popup).

So first execute the first While, then execute the second While of the exception (which skips a single button), then return to the first While that continues to click on subsequent buttons (after the jumped button). The purpose of the second While is to call it whenever no "Add Friend" button can be pressed, so its purpose is to skip an "Add Friend" button, then resume clicking subsequent buttons (after skipping a button). This was my idea, but I'm not sure I wrote the second While code well

I tried adding a try and except to the above code. The exception is this (i approach the solution, but there is something wrong):

except ElementClickInterceptedException:
    print("A button cannot be pressed. You go to the next button ...")

    close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()

    #I skip a button, add only one (1) friend, then stop, and it's back to the main loop for to add and click on all friends
    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
            

I had thought of this solution, but I don't know if it is right. I had thought that when I get that popup, it can momentarily start an increment of 2 to skip the button. After this, we close the increment of 2 and this while loop, and then we return to the main while loop. Maybe another solution would be that if the same button is clicked twice, then you have to skip it

How can I solve the problem? Can you suggest a code answer please? Thanks

This is the complete and executable code (including GUI) in case anyone would like to test and help me. I don't want spam problems, so I created the possibility to choose for example 5 people to send the request to. This script is for my own study purposes only:

    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
    
    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/3985338151528881") #example link
    
    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, "5")
    
    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)
    
    
    def start_with_limits(): 
        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') ########### CHANGE YOUR PATH
        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

        try:
    
            while i <= limit:
                i = i + 1
    
                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, add)
                time.sleep(delay)
    
                #code for close popup
                #close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()
    
    
        except ElementClickInterceptedException:
            print("A button cannot be pressed. You go to the next button ...")

            close_popup = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Ok']"))).click()

            #I skip a button, add only one (1) friend, then stop, and it's back to the main loop for to add and click on all friends
            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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夕嗳→ 2025-01-30 09:46:34

由于您在刮擦信息时正在更改网站,因此您的循环无法按照您希望的方式工作。

我将推荐首先获取所需的信息,然后再处理槽:

rows = driver.find_elements(
    by=By.XPATH,
    value=f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])"
)

for row in rows:
    driver.execute_script("arguments[0].scrollIntoView(true);", row)
    add_button = driver.find_element(
        by=By.XPATH,
        value="//span[text()='Add Friend']"
    )

    add_button.click()
    
    time.sleep(delay)

    try:
        close_popup_button = driver.find_element(
            by=By.XPATH,
            value="//span[text()='Ok']"
        )
        close_popup_button.click()
    except NoSuchElementException:
        pass

这可能在动态加载的内容上可以很好地扩展,但是为此目的是足够的。

如果您想添加此类行为,我会看一下集合,以确保没有重复的值且效率更高。

然后,您可以有一个循环,可以执行以下操作,直到找不到任何新值。

  1. 找到每个元素的所需元素
    1. 测试元素是否在已经单击的元素
    2. 如果是的,请什么都不做,如果不单击元素并将其添加到集合
  2. 滚动到页面的底部

since you are changing the site as you scrape the information, your loop wont work the way you want it to work.

i would recomment to first get the information you need and then work trough it:

rows = driver.find_elements(
    by=By.XPATH,
    value=f"(//div[@data-visualcompletion='ignore-dynamic' and not (@role) and not (@class)])"
)

for row in rows:
    driver.execute_script("arguments[0].scrollIntoView(true);", row)
    add_button = driver.find_element(
        by=By.XPATH,
        value="//span[text()='Add Friend']"
    )

    add_button.click()
    
    time.sleep(delay)

    try:
        close_popup_button = driver.find_element(
            by=By.XPATH,
            value="//span[text()='Ok']"
        )
        close_popup_button.click()
    except NoSuchElementException:
        pass

this might not scale very well with content that is dynamically loaded in, but for this purpose it is enough.

if you ever want to add such behavior, i would take a look at sets, which ensure that there are no duplicate values and are somewhat more efficient.

you could then have a loop that does the following until it does not find any new values.

  1. find desired elements
  2. for each element:
    1. test if element is in set of already clicked elements
    2. if yes, do nothing, if not click on element and add it to the set
  3. scroll to the bottom of the page
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文