excel 使用FindElementbyXpath()获取Selenium Basic中可填充框的行和列名

xdnvmnnf  于 2023-04-22  发布在  其他
关注(0)|答案(2)|浏览(161)

我正在使用SeleniumBasic从我的电子表格向一个网站填充文本。

<div>
    <table cellspacing="0" rules="all" border="1" id="ctl00_ContentPlaceHolder1_GridView1" style="width:99%;border-collapse:collapse;">
        <tr>
            <th scope="col" style="font-weight:bold;">FX</th>
            <th scope="col" style="color:White;">Pic</th>
            <th scope="col">Cash</th>
            <th scope="col">Bid</th>
            <th scope="col">Ask</th>
        </tr>
        <tr>
            <td style="font-weight:bold;">
                <span id="ctl00_ContentPlaceHolder1_GridView1_ctl02_Label1">USD1</span>
            </td>
            <td> &nbsp; <img id="ctl00_ContentPlaceHolder1_GridView1_ctl02_Image1" src="UploadFiles/QLTG-File/MH_200931393922.jpg" style="border-width:0px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl02$txtCash" type="text" value="4" id="ctl00_ContentPlaceHolder1_GridView1_ctl02_txtCash" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl02$txtBid" type="text" value="5" id="ctl00_ContentPlaceHolder1_GridView1_ctl02_txtBid" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl02$txtAsk" type="text" value="6" id="ctl00_ContentPlaceHolder1_GridView1_ctl02_txtAsk" style="width:100px;" />
            </td>
        </tr>
        <tr>
            <td style="font-weight:bold;">
                <span id="ctl00_ContentPlaceHolder1_GridView1_ctl03_Label1">USD2</span>
            </td>
            <td> &nbsp; <img id="ctl00_ContentPlaceHolder1_GridView1_ctl03_Image1" src="UploadFiles/QLTG-File/MH_20093139406.jpg" style="border-width:0px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl03$txtCash" type="text" value="7" id="ctl00_ContentPlaceHolder1_GridView1_ctl03_txtCash" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl03$txtBid" type="text" id="ctl00_ContentPlaceHolder1_GridView1_ctl03_txtBid" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl03$txtAsk" type="text" id="ctl00_ContentPlaceHolder1_GridView1_ctl03_txtAsk" style="width:100px;" />
            </td>
        </tr>
        <tr>
            <td style="font-weight:bold;">
                <span id="ctl00_ContentPlaceHolder1_GridView1_ctl04_Label1">USD3</span>
            </td>
            <td> &nbsp; <img id="ctl00_ContentPlaceHolder1_GridView1_ctl04_Image1" src="UploadFiles/QLTG-File/MH_201441583814.jpg" style="border-width:0px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl04$txtCash" type="text" value="    " id="ctl00_ContentPlaceHolder1_GridView1_ctl04_txtCash" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl04$txtBid" type="text" id="ctl00_ContentPlaceHolder1_GridView1_ctl04_txtBid" style="width:100px;" />
            </td>
            <td align="right"> &nbsp; <input name="ctl00$ContentPlaceHolder1$GridView1$ctl04$txtAsk" type="text" id="ctl00_ContentPlaceHolder1_GridView1_ctl04_txtAsk" style="width:100px;" />
            </td>
        </tr>
    </table>
</div>

我想找到一个可填充框的行和列名,假设这个元素是由fillableBoxes = driver.FindElementsByXPath("//input[@type='text']")得到的。
例如,我尝试获取可填充框的特定行和列

Table = driver.FindElementById("ctl00_ContentPlaceHolder1_GridView1")
Example = Table.FindElementById("ctl00_ContentPlaceHolder1_GridView1_ctl03_txtBid")
Dim rowElement As WebElement
Set rowElement = Example.FindElementByXPath("./ancestor::tr")
Dim columnHeaderElement As WebElement
Set columnHeaderElement = Example.FindElementByXPath("./ancestor::table/descendant::tr[1]/th[position() = count(./preceding-sibling::td)+1]")

Dim rowName As String
rowName = rowElement.FindElementByXPath("./th").Text
    
Dim columnName As String
columnName = columnHeaderElement.Text

错误是

NoSuchElementError - Element not found for Xpath=./th

调试停止在

rowName = rowElement.FindElementByXPath("./th").Text

看来我把XPath搞错了。我怎样才能得到正确的XPath来获取行和列名呢?

mkshixfv

mkshixfv1#

由于你可能会重复使用这些代码,我发现写一个Sub是最简单的,这样使用/重用就很容易了。在这种情况下,我们可以写一个Sub,它接受列标签、行标签和所需的文本,并根据列标签和行标签在单元格中找到的INPUT中设置所需的文本。

Sub SetCell(ColLabel As String, RowLabel As String, Text As String)
    ' store the long JS commands to return the indexes
    ColIndexExp = """return document.evaluate(""count(//table[@id='ctl00_ContentPlaceHolder1_GridView1']//th[text()='" & ColLabel & "']/preceding::th) + 1"", document, null, XPathResult.NUMBER_TYPE, null).numberValue"""
    RowIndexExp = """return document.evaluate(""count(//table[@id='ctl00_ContentPlaceHolder1_GridView1']//tr[./td/span[text()='" & RowLabel & "']]/preceding::tr) + 1"",  document, null, XPathResult.NUMBER_TYPE, null).numberValue"""
    ' execute the JS commands and store the values
    ColIndex = ExecuteScript(ColIndexExp)
    RowIndex = ExecuteScript(RowIndexExp)
    ' print the values to the console for debugging, can be safely removed
    Debug.Print ColIndex
    Debug.Print RowIndex
    ' set the desired text in the appropriate cell based on the labels provided
    driver.FindElementByXPath("//table[@id='ctl00_ContentPlaceHolder1_GridView1']//tr[" & RowIndex & "]/td[" & ColIndex & "]/input").SendKeys (Text)
End Sub

那就叫像

SetCell "Bid", "USD1", "ABCD"
fbcarpbf

fbcarpbf2#

下面的代码在Excel中为我工作,VBA和SeleniumBasic与Edge浏览器。每一个注解掉的行都可以工作,并显示了我如何构建最终的XPath来挑选TABLE html中的特定INPUT框。我将结果html作为文本文件编写出来,因为使用文本编辑器来理解所选html的情况总是很有用的。XPath的最后一段选择第二行的第二个输入字段的Id-Cash字段。

Option Explicit
Sub sbXPathTableInput()
    Dim driver As ChromeDriver
    Set driver = New ChromeDriver
    Dim sURL As String
    Dim we As WebElement
    sURL = "https://davetallett26.github.io/table.html"
    Dim sFilename As String
    Call driver.Start("edge", sURL)
    driver.get (sURL)
    driver.Window.Maximize
    sbDelay (100000)
    Set we = driver.FindElementByXPath("/html/body")
    sFilename = "C:\Users\david\Downloads\out-" & Format(Now(), "yyyymmddHHMMSS") & ".txt"
    Open sFilename For Output As #1
'    Print #1, we.FindElementByXPath("/html/body").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("/html/body/div/table").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr[2]").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("//input").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr[2]/following::input[1]").Attribute("outerHTML")
'    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr[2]/following::input[1]").Attribute("name")
'    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr[2]/following::input[1]").Attribute("id")
    ' second row, second input field
    Print #1, we.FindElementByXPath("/html/body/div/table/tbody/tr[2]/following::input[2]").Attribute("id")  
    Close #1
    sbDelay (100000)
    driver.Quit
End Sub

Sub sbDelay(delay As Long): Dim i As Long: For i = 1 To delay:  DoEvents: Next i: End Sub 'old skool delay

相关问题