使用 selenium 选择下拉框时,只有点击下拉框底下的数据,浏览器 F12 时的代码才能看到下拉框元素的位置,下拉框数据是封装在接口里面的,这种的该怎么定位
先点击下拉框元素,再查找及点击出来的其中一个子元素?
只要你查找的那一刻,元素有在 dom 树里面,就可以找到。
怎么选中下拉框数据,这是 selenium 定位元素基本操作,加那么多定语干嘛
这个是封装在接口里面的,selenium 那个是直接把下拉框的数据写在代码中,直接能看到的,这个是只有点击元素,元素位置才会显示在源代码中
但是运行 python 代码的时候下拉框的数据会因为没有点击的点位找不到的,就算手动点击后源代码里面的数据写到 python 代码上还是提示找不到该位置
没看懂你的问题,到底是手动在 F12 里没定位到元素,还是自动化运行过程中定位不到。如果是说因为点击才出现,然后审查元素时就消失,那可能是受了点击事件的影响。你可以试试设置页面断点,一步步调试代码,这样点击出现的元素在审查是不会消失。。
如果是自动化运行过程中找不到,那你要看看你写的定位方式是不是正确,然后看看等待的时间是否合理。
就你现在的代码,截图或者直接贴内容都可以,想看看你现在是不是用了错误的姿势来做下拉框操作,所以定位不到。
一般下拉框会有两种实现,一种是 html 自带的 select + option 标签,selenium 对应 api 是 select_by_index 等专门的 api。另一种是用 div 标签模拟的下拉框(实际值存在一个 input 标签里),这种就按照用户的操作顺序,一个一个来 定位元素 + 点击 就可以。
另外,既然你都可以截图看到 dom 树里面点击后更新的内容了,为啥你一直说 selenium 找不到呢?我在 1 楼已经说了,你这个加载是通过点击下拉框才触发,那自动化里也点击下拉框后再找,不应该找不到呀(涉及网络有可能立即找还没加载出来,可以加个显式等待)。
我使用了两种方法:
首先是 selenium 的 click 点击下拉框,然后点击下拉框下的元素,这种方法点击不上下拉框的元素
第二种是使用了 Select 这个包对下拉框的数据进行定位,还是不成功
self.base.click(section="add_Basic_population_jump", option="House_registration_register") 这个函数的具体实现是怎样的,发一下?需要细到能看到调用的是哪个 selenium python 库的方法,现在你封装了不知道里面做的啥操作。
selenium 的 select 相关 api 是肯定不行的,报错里已经说了只能用于 select 标签元素,不能用于 div 标签。
这里面不同定位策略你逻辑还不一样,看起来比较麻烦。
或者你不要用你封装的,直接用 selenium python 库自带的函数 (driver.find_element 以及 click 方法) 来写看看?就写两次点击这个方式的就行。
运行两次点击会报:AttributeError: 'NoneType' object has no attribute 'click'
你把你代码改用纯 selenium python 库方法写一遍,然后运行。把你的代码 + 运行错误日志贴上来吧。
你现在这样也看不出为啥你自己封装的一个 __find_element__(section, option)
会返回一个 None ,与其花时间逐层看你的封装有没有问题,还不如你直接去掉所有封装,直接写代码发上来。
import time
import os
from selenium import webdriver
from common.basic import Base
from common.read_image import ocr
from selenium.webdriver.common.by import By
from config.conf import img_address
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://wlsq.daishan.gov.cn/ddWeb/user/login")
time.sleep(10)
# 登录
driver.find_element(By.XPATH, '//span[@class = "ant-input-affix-wrapper ant-input-affix-wrapper-lg"]/input[@placeholder="请输入帐户名"]').send_keys("cxc")
driver.find_element(By.XPATH, '//span[@class = "ant-input-affix-wrapper ant-input-affix-wrapper-lg"]/input[@placeholder="请输入密码"]').send_keys("admin123456?")
img = Base(driver).screenshot(os.path.join(img_address, str(int(time.time())) + ".png"))
text = ocr(img)
driver.find_element(By.XPATH, '//span[@class = "ant-input-affix-wrapper ant-input-affix-wrapper-lg"]/input[@placeholder="请输入验证码"]').send_keys(text)
driver.find_element(By.XPATH, '//button[@class="login_btn"]').click()
time.sleep(20)
# 点击基础数据
driver.find_element(By.XPATH, "//html[@id='htmlRoot']//div[@id='app']/div[@class='home-large']/div[@class='home-large-content']//div[@class='slick-track']/div//div[@class='home-large-content-item']//span[.=' 基础数据库 ']").click()
time.sleep(5)
# 添加基础人口
driver.find_element(By.XPATH, "//div[@class='table-operator']/button[@class='ant-btn ant-btn-primary']").click()
time.sleep(5)
# 输入姓名
driver.find_element(By.XPATH, "//div[@class='ant-form-item-control']/span[@class='ant-form-item-children']/input[@id='name']").send_keys("小龙")
time.sleep(5)
# 出生日期
driver.find_element(By.XPATH, "//span[@class='ant-calendar-picker']/div/input[@placeholder='请选择出生日期']").click()
# 出生日期输入框
driver.find_element(By.XPATH, "//div[@class='ant-calendar-panel']/div[@class='ant-calendar-input-wrap']/div[@class='ant-calendar-date-input-wrap']/input[@placeholder='请选择出生日期']").send_keys("1858-02-02")
# 点击地址
time.sleep(5)
driver.find_element(By.XPATH, '//input[@id="building_address_info"]').click()
# 点击地址页面搜索框
driver.find_element(By.CSS_SELECTOR, 'input[placeholder="请输入地址"]').send_keys("舟山市岱山县外达昆西南约330米")
time.sleep(5)
# 地址库页面查询按钮
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[5]/div/div[@role='dialog']/div[@role='document']//form[@class='ant-form ant-form-inline']/div[@class='ant-row']//span[@class='table-page-search-submitButtons']/button[1]").click()
# 地址库页面选中数据
driver.find_element(By.XPATH, '//table[@class="ant-table-fixed"]/tbody[@class="ant-table-tbody"]/tr[@class="ant-table-row ant-table-row-level-0"]/td[3]').click()
# 地址库页面点击确定
driver.find_element(By.XPATH, '//div[@class="ant-modal-footer"]/div/button[2]').click()
time.sleep(5)
# 选择户口类别
driver.find_element(By.XPATH, '//div[@class="ant-form-item-control"]/span/div[@id="household_registration_category"]/div[@role="combobox"]/div').click()
# 选择户籍人口
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[5]/div/div[@role='dialog']/div[@role='document']//div[@class='ant-select-dropdown-content']/ul[@role='listbox']/li[1]/span[@title='户籍人口']").click()
# 选择性别
driver.find_element(By.XPATH, "//html[@id='htmlRoot']//div[@id='sex']//div[@class='ant-select-selection__placeholder']").click()
# 男
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[3]/div/div[@role='dialog']/div[@role='document']//div[@class='ant-select-dropdown-content']/ul[@role='listbox']/li[2]/span[@title='男']").click()
# 联系方式
driver.find_element(By.XPATH, "//html[@id='htmlRoot']//input[@id='phone_number']").send_keys("15203141442")
# 证件号码
driver.find_element(By.XPATH, "//html[@id='htmlRoot']//input[@id='id_card']").send_keys("42010119720727663X")
# 入户状态
driver.find_element(By.XPATH, "//html[@id='htmlRoot']//div[@id='household_status']//div[@class='ant-select-selection__placeholder']").click()
# 点击一致
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[3]/div/div[@role='dialog']/div[@role='document']/div[@class='ant-modal-content']/div[5]/div/div[@class='ant-select-dropdown ant-select-dropdown--single ant-select-dropdown-placement-bottomLeft']/div[@class='ant-select-dropdown-content']/ul[@role='listbox']/li[1]/span[@title='一致']").click()
# 点击确定
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[3]/div/div[@role='dialog']/div[@role='document']//div[@class='ant-modal-footer']/button[1]")
time.sleep(10)
driver.close()
运行后
Traceback (most recent call last):
File "D:/dingdang_project/DDJX_ChangTu/libs/Q_test.py", line 69, in <module>
driver.find_element(By.XPATH, "//html[@id='htmlRoot']/body/div[5]/div/div[@role='dialog']/div[@role='document']//div[@class='ant-select-dropdown-content']/ul[@role='listbox']/li[1]/span[@title='户籍人口']").click()
File "D:\work software\python3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element
'value': value})['value']
File "D:\work software\python3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "D:\work software\python3\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//html[@id='htmlRoot']/body/div[5]/div/div[@role='dialog']/div[@role='document']//div[@class='ant-select-dropdown-content']/ul[@role='listbox']/li[1]/span[@title='户籍人口']"}
(Session info: chrome=99.0.4844.51)
你的户籍人口这个控件的 xpath 是怎么来的,有确认过这个 xpath 的正确性吗?这个控件查找的时候加个显式等待试试(因为从你描述看,应该是请求网络成功过后才会出现这个元素,所以点击后立即找有可能网络还没返回,所以找不到)
可以在 chrome 浏览器的 审查元素 - 元素 tab 用 xpath 搜索,看看在你点击了下拉框加载到数据后进行搜索,是否有搜索到结果。
汗 ,这个项目难以定位元素,图方便,使用了浏览器的获取 xpath,控件的 xpath 是正确的,我修改一下,加上显式等待试试