【问题标题】:Selelnium - Python | Date of Birth fields by using Label硒 - Python |使用标签的出生日期字段
【发布时间】:2020-08-13 12:17:54
【问题描述】:

我想创建 GENERIC python 代码,它将日、月和年填入正确的字段。

但不知道怎么做。

在第一个例子中,我们可以看到labelinput 之间通过使用for 参数建立了联系(但是我们需要从标签中获取for 参数并以某种方式检查它是否包含日、月等)

在第二个示例中,我们可以看到 input 没有任何 ID,通过 span 包装器。所以我们可以将labelspan 联系起来,然后以某种方式使用following::/input[0,1,2] 查找DAY、MONTH 等。

问题:是否有任何可能的方法来创建适用于第一个和第二个示例的通用代码?任何最佳做法?

第一个网站:

<div data-readonly="False">
   <label for="Applicants_0__DateOfBirth">Date of birth</label>
   <div class="rhsForm">
      <input type="text" class="split-date-hidden hasDatepicker" id="dp1587032701992">
      <input class="split-date-day" data-val="true" data-val-number="Please enter a valid date (day)" data-val-range="Please enter a valid date (day)" data-val-range-max="31" data-val-range-min="1" id="Applicants_0__DateOfBirth_Day" maxlength="2" name="Applicants[0].DateOfBirth.Day" placeholder="DD" type="text" value="">
      <span class="field-validation-valid" data-valmsg-for="Applicants[0].DateOfBirth.Day" data-valmsg-replace="true"></span>
      <span class="split-date-separator">&nbsp;</span>
      <input class="split-date-month" data-val="true" data-val-number="Please enter a valid date (month)" data-val-range="Please enter a valid date (month)" data-val-range-max="12" data-val-range-min="1" id="Applicants_0__DateOfBirth_Month" maxlength="2" name="Applicants[0].DateOfBirth.Month" placeholder="MM" type="text" value="">
      <span class="field-validation-valid" data-valmsg-for="Applicants[0].DateOfBirth.Month" data-valmsg-replace="true"></span>
      <span class="split-date-separator">&nbsp;</span>
      <input class="split-date-year" data-val="true" data-val-number="Please enter a valid date (year)" data-val-range="Please enter a valid date (year)" data-val-range-max="5000" data-val-range-min="1000" id="Applicants_0__DateOfBirth_Year" maxlength="4" name="Applicants[0].DateOfBirth.Year" placeholder="YYYY" type="text" value="">
      <span class="field-validation-valid" data-valmsg-for="Applicants[0].DateOfBirth.Year" data-valmsg-replace="true"></span>
      <img class="split-date-calendar-button" src="./Create a case _ the Coventry for intermediaries 3_files/CalendarIcon.png" alt="Show calendar">
      <span class="field-validation-valid" data-valmsg-for="Applicants[0].DateOfBirth" data-valmsg-replace="true"></span>
   </div>
</div>

第二个网站:

<div class="sel formItemContainer" f-class="EntryRow" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False">
    <div class="emc" id="Entry.Customer.C1.BirthDateEmc" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False"></div>
    <label class="sc" for="Entry.Customer.C1.BirthDate" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False">Date of birth</label>
    <div class="si" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False">
      <span f-class="PatternEntry" f-iscustom="True" f-valuetype="Date" f-minimumlength="3" f-validationname="date of birth" f-isrequired="True" f-isrequiredrule="System.True" f-isreadonlyrule="Data.Customers.C1.AuthenticatedOrPersonalDetailsReadOnly" id="Entry.Customer.C1.BirthDate" value="23/02/1990" f-entryname="Customer.C1.BirthDate" f-submitsdata="True" class="date" xmlns:msxsl="urn:schemas-microsoft-com:xslt" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False" f-readonlyruleresult="False">
        <input type="text" f-class="PatternPart" f-iscustom="True" f-behaviours="formItemChanged" value="444" maxlength="2" size="2" f-parttype="substring" f-partstart="1" f-partlength="2" f-isreadonly="False" f-hasreadonlyrulebeenappliedbefore="True" c-originalvalue="23/02/1989">
        <span f-class="PatternPart" f-parttype="static" f-value="/" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False">/</span>
        <input type="text" f-class="PatternPart" f-iscustom="True" f-behaviours="formItemChanged" value="02" maxlength="2" size="2" f-parttype="substring" f-partstart="4" f-partlength="2" f-isreadonly="False" f-hasreadonlyrulebeenappliedbefore="True" c-originalvalue="23/02/1989">
        <span f-class="PatternPart" f-parttype="static" f-value="/" f-hasreadonlyrulebeenappliedbefore="True" f-isreadonly="False">/</span>
        <input type="text" f-class="PatternPart" f-iscustom="True" f-behaviours="formItemChanged" value="1989" maxlength="4" size="4" f-parttype="substring" f-partstart="7" f-partlength="4" f-isreadonly="False" f-hasreadonlyrulebeenappliedbefore="True" c-originalvalue="23/02/1989">
        </span>
    </div>
</div>

让我们使用参数:

d = '01'
m = '02'
y = '1933'

ar = [d,m,y]

那么potential 代码将是:

l = 'Date of birth'
fls = browser.find_elements_by_xpath('//label[contains(.,"{}")]'.format(l))
    if fls:
        # loop through array <<ar>> and pass each value one by one  
        element = browser.find_elements_by_xpath('//*[@id="{}"]'.format(fls[0].get_attribute("for")))

        if element:
            containtInput = element[0].tag_name.lower() == "input"
            if containtInput:
                x = element[0].find_elements_by_xpath(./following::/input[0])
                x.send_keys(value)
                break

【问题讨论】:

    标签: python html selenium input automation


    【解决方案1】:

    我不认为在通用解决方案上花费太多时间是一个好主意,因为如果页面特定的解决方案做得好就很容易。如果您确定要使用的所有页面都使用 DD/MM/YYYY 格式并且所有字段都是数字,那么您可以尝试这样的操作:

    def fill_date(input_holder_div, data):
        fields = input_holder_div.find_elements_by_xpath('./input[@type="text"]')
        for i in range(3):
            fields[-i-1].clear()
            fields[-i-1].send_keys(data[-i-1])
    
    my_date = [11, 11, 1980]
    # fill_date(driver.find_element_by_xpath('//*[@f-class="EntryRow"]'), my_date)
    # fill_date(driver.find_element_by_xpath('//*[@class="rhsForm"]'), my_date)
    

    使用正确的父级和数据调用函数,工作就完成了。 -i-1 部分只需要填写最后 3 个输入字段,如果存在此类元素,则忽略隐藏的输入字段。但也有副作用。

    如果页面不包含仅包含这 3 个输入文本字段的父元素怎么办。如果您遇到日期格式为 YYYY/MM/DD 或月份按名称选择的页面怎么办...

    如果您想在两种不同的布局上执行非常相似或相同的工作流程,那么您可能应该查看page object approach。这个概念是你在一个类中定义如何在页面上做事,然后调用方法,它们就会做他们想做的事情。

    例子:

    class BasePage:
    
        def __init__(self, driver):
            self.driver = driver
    
        @staticmethod
        def _fill(input_element, data):
            input_element.clear()
            input_element.send_keys(data)
    
    
    class FirstPage(BasePage):
    
        def fill_day(self, data):
            field = self.driver.find_element_by_xpath('//*[@class="split-date-day"]')
            self._fill(field, data)
    
    
    class SecondPage(BasePage):
    
        def fill_day(self, data):
            field = self.driver.find_element_by_xpath('//*[@id="Entry.Customer.C1.BirthDate"]/input')
            self._fill(field, data)
    

    您有 FirstPage 和 SecondPage 类,它们知道如何做事,例如如何填写日期输入字段。如果你完成了这两个类(并添加了fill_monthfill_year 方法),你可以使用相同的逻辑处理日期填充:

    def fill_date(page, data):
        page.fill_day(data[0])
        page.fill_month(data[1])
        page.fill_year(data[2])
    
    
    first_page = FirstPage(driver)
    second_page = SecondPage(driver)
    
    if first_page_is_loaded:
        fill_date(first_page, my_data)
    else:
        fill_date(second_page, my_data)
    
    

    如果页面的工作流程非常相似,您只需使用正确的页面对象即可。您可以通过将一些逻辑移动到页面对象来处理细微的差异,并在主逻辑中使用相同的流程。

    【讨论】:

      猜你喜欢
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 2021-03-26
      • 2019-03-31
      • 1970-01-01
      相关资源
      最近更新 更多