这是一个让开始接触web自动化,手持AI还是掉了999根头发还解决不了的概率问题

0 <总之现在的代码和屎山没区别,雕虫小技,佬友们勿喷,希望能指点一下,处理这种元素,如何实现精确的定位。我认为还是定位有问题。>

1、需求:通过在指定位置输入名字,然后自动搜索到人,进行选择即可。页面大概长这样:

2、目前的代码部分,总是在填完几个表单后,总是会出现已经搜索到但是一直报找不到,很郁闷,十八般武艺,试过延时,更改xpath等等都上场总是解决不了这个随机问题,压测一下很快就会出现。

3、上来,佬友们先看代码部分。这部分是找到指派人的名字,将名字填入到web的内容输入框,搜到这个指派人,然后选择它填入。

        if "指派给" in data:
            input_executor_name = data["指派给"]
            if input_executor_name:
                executor_name = get_employee_name(input_executor_name)
                if executor_name:  # 确保创建人不为空
                    try:
                        # 使用唯一的 div id 定位输入框所在的容器
                        container = WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.ID, 'field-item-fldqVXMJ5f'))
                        )
                        # 滚动到截止日期元素
                        driver.execute_script("arguments[0].scrollIntoView();", WebDriverWait(driver, 10).until(
                            EC.presence_of_element_located((By.ID, 'field-item-fldqVXMJ5f'))
                        ))
                        # 2. 点击下拉框触发器 (using XPath for more precise location)
                        dropdown_trigger = WebDriverWait(container, 10).until(
                            EC.element_to_be_clickable((By.XPATH,
                                                        "//*[@id='field-item-fldqVXMJ5f']//div[contains(@class, 'bitable-38bc4d__select-dropdown')]"))
                        )
                        dropdown_trigger.click()  # 点击以激活输入框

                        # 删除现有标签
                        remove_tags = container.find_elements(By.CSS_SELECTOR, 'span.universe-icon.b-user-tag-close')
                        for remove_tag in remove_tags:
                            remove_tag.click()
                            WebDriverWait(driver, 1).until(EC.staleness_of(remove_tag))  # 等待元素消失

                        # 在 container 内部定位输入框
                        search_input = WebDriverWait(container, 10).until(
                            EC.visibility_of_element_located((By.CSS_SELECTOR, 'input.b-select-search'))
                        )
                        # 使用 JavaScript 设置输入框的值
                        driver.execute_script("arguments[0].value = arguments[1];", search_input, executor_name)

                        # 触发输入框的 input 事件
                        driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));",
                                              search_input)
                        # 等待并选择下拉选项,使用executor_name动态查找
                        time.sleep(1)
                        # 定义多个定位器策略,依次尝试找到包含 executor_name 的下拉选项
                        locators = [
                            # 策略1:直接定位包含 executor_name 的选项
                            (By.XPATH,
                             f"//div[contains(@class, 'larkw-option-item') and .//span[contains(normalize-space(.), '{executor_name}')]]"),
                            # 策略2:从 b-select-dropdown-container 父节点下查找
                            (By.XPATH,
                             f"//div[contains(@class, 'b-select-dropdown-container')]//div[contains(@class, 'larkw-option-item') and .//span[contains(normalize-space(.), '{executor_name}')]]"),
                            # 策略3:从 b-select-dropdown-content 父节点下查找
                            (By.XPATH,
                             f"//div[contains(@class, 'b-select-dropdown-content')]//div[contains(@class, 'larkw-option-item') and .//span[contains(normalize-space(.), '{executor_name}')]]"),
                            # 策略4:先定位包含 executor_name 的 span,再回溯到祖先的选项元素
                            (By.XPATH,
                             f"//span[contains(normalize-space(.), '{executor_name}')]/ancestor::div[contains(@class, 'larkw-option-item')]")
                        ]

                        option_to_select = None

                        for locator in locators:
                            try:
                                option_to_select = WebDriverWait(driver, 5).until(
                                    EC.visibility_of_element_located(locator)
                                )
                                print(f"使用定位器 {locator} 成功找到元素")
                                # 调试3:打印找到元素的 outerHTML 和 innerText
                                element_html = option_to_select.get_attribute("outerHTML")
                                element_inner_text = driver.execute_script("return arguments[0].innerText;",
                                                                           option_to_select)
                                print("找到的元素 outerHTML:")
                                print(element_html)
                                print("找到的元素 innerText:")
                                print(element_inner_text)
                                break  # 找到元素后退出循环
                            except Exception as e:
                                print(f"定位器 {locator} 未能找到元素,继续尝试下一个... 异常信息:{e}")

                        if option_to_select:
                            option_to_select.click()
                        else:
                            print("未找到包含执行者名称的下拉选项,请检查页面结构或 executor_name 是否正确。")
                    except Exception as e:
                        dropdown_trigger.click()
                        print(f"处理 '指派给' 失败(行 {row_index}):{e}")
                        # continue
            else:
                print(f"输入的 '指派给' 名称 '{input_executor_name}' 未能匹配到任何已知的员工。")

期间,我想要打印下拉框的内容,当然得通过AI给我以下代码 :rofl:进行调试,打印出来压根就不是我看到的内容。-不管怎么样都打印不出来下拉框里的内容,也希望佬友们能指点一下。

    dropdown_container = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'b-select-dropdown-container')]"))
    )
    
    # 调试1:打印下拉框容器的 outerHTML
    container_html = dropdown_container.get_attribute("outerHTML")
    print("调试1:下拉框容器 outerHTML如下:")
    print(container_html)
    
    # 调试2:使用 JavaScript 获取并打印下拉框容器的 innerText
    container_inner_text = driver.execute_script("return arguments[0].innerText;", dropdown_container)
    print("调试2:下拉框容器 innerText如下:")
    print(container_inner_text)

#这是元素部分


点开这个id是以下

元素内容.txt (3.7 KB)

如果有姥友指点一二,就先谢谢过了,走过路过不要错过。我已经调试了几百次,当然21世纪的发明AI也都尝试了,可依然无济于事。因为这个问题,整套代码调测已过544次了。

1 个赞

这个要加延迟,判断元素是否出现,手撸代码就几下子.

搜索触发后,先找到搜索结果的下拉框,然后在下拉框里面找你需要点击的元素

判断那个元素是否显示,最简单的方法是,点击下拉后,等待2秒,再执行点击下拉框的内容

用 dp 快得很,不容自己写这么判断

你这不是先有名字,你不能直接修改内容然后触发事件吗?

姥友能否指点一下

姥友能详述吗?

尝试等待了,完全没有用

现在就是这个逻辑的

是啊,我试了延迟,但是就是没有用

虽然你是这么想的,但代码不是这样写的呀。另外也可以直接搜带目标人名的文本节点,然后向上找 select

输入人名之后,需要触发搜索。
然后下拉框中会出现搜索到的人物
考虑到重名,需要定位是哪一个,然后执行选择。
现在的逻辑是这样的。姥友能給下示例吗

  1. 把这段代码使用 search_input.send_keys(executor_name) 替换

  2. 把选中节点的逻辑移动到 JavaScript 中去

script="""
const executor_name = arguments[0];

// 由于筛选结果可能需要网络请求,这里延时 3s,去选中目标
setTimeout(() => {
  const item = document.querySelector('.larkw-option-item--highlight')

  // item 可能有多个,自行筛选
  // 需要点击的节点可能是这个节点的父级,自行向上 .parent

  item.click()
}, 3000)
"""

driver.execute_async_script(script, executor_name)