Iterate through table rows and print column text with Python Selenium

Question:

I have a table (<table>) with values in each row (<tr>) from its body (<tbody>).

The value I would lile to print out is in the <span> inside a <div> tag.

Inspecting the html, I see the value e.g. “Name” is in row 1 (tr[1]), column 2 (td[2]):

<tr class="GAT4PNUFG GAT4PNUMG" __gwt_subrow="0" __gwt_row="0">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUHG GAT4PNUNG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUNG">
                <div __gwt_cell="cell-gwt-uid-324" style="outline-style:none;">
                    <span class="linkhover" title="Name" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;color:#00A;cursor:pointer;">Name</span>
                </div>
            </td>

I would like to loop through the table each row and print out the value in columns 2, td[2]

I am using Python with Selenium Webdriver

The full Xpath to the table row 1, column 2 is:

html/body/div[2]/div[2]/div/div[4]/div/div[2]/div/div[3]/div/div[5]/div/div[3]/div/div[4]/div/div[2]/div/div[4]/div/div[3]/div/div[2]/div/div/table/tbody/tr[1]/td[2]/div/span

I was thinking if i can start from the table, xpath as follows:

html/body/div[2]/div[2]/div/div[4]/div/div[2]/div/div[3]/div/div[5]/div/div[3]/div/div[4]/div/div[2]/div/div[4]/div/div[3]/div/div[2]/div/div/table/tbody

I can then use a for loop and use an index for the tr and td
e.g for row1 use tr[i], for col2 use td[2].

html/body/div[2]/div[2]/div/div[4]/div/div[2]/div/div[3]/div/div[5]/div/div[3]/div/div[4]/div/div[2]/div/div[4]/div/div[3]/div/div[2]/div/div/table/tbody/tr[i]/td[2]/div/span

How can i loop through this table and print out the value of the Span class tag which is always in column 2 of the table?

I tried to get the start of the table into a variable and then I could maybe use this to loop through the rows and columns.
I need some help please.

table = self.driver.find_element(By.XPATH, 'html/body/div[2]/div[2]/div/div[4]/div/div[2]/div/div[3]/div/div[5]/div/div[3]/div/div[4]/div/div[2]/div/div[4]/div/div[3]/div/div[2]/div/div/table/tbody')

Here’s the full HTML:

    <table cellspacing="0" style="table-layout: fixed; width: 100%;">
    <colgroup>
    <tbody>
        <tr class="GAT4PNUFG GAT4PNUMG" __gwt_subrow="0" __gwt_row="0">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUHG GAT4PNUNG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUNG">
                <div __gwt_cell="cell-gwt-uid-324" style="outline-style:none;">
                    <span class="linkhover" title="Name" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;color:#00A;cursor:pointer;">Name</span>
                </div>
            </td>
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUNG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUNG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUNG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUBH GAT4PNUNG">
        </tr>
        <tr class="GAT4PNUEH" __gwt_subrow="0" __gwt_row="1">
            <td class="GAT4PNUEG GAT4PNUFH GAT4PNUHG">
            <td class="GAT4PNUEG GAT4PNUFH">
                <div __gwt_cell="cell-gwt-uid-324" style="outline-style:none;">
                    <span class="linkhover" title="Address" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;color:#00A;cursor:pointer;">Address</span>
                </div>
            </td>
            <td class="GAT4PNUEG GAT4PNUFH">
            <td class="GAT4PNUEG GAT4PNUFH">
            <td class="GAT4PNUEG GAT4PNUFH">
            <td class="GAT4PNUEG GAT4PNUFH GAT4PNUBH">
        </tr>
        <tr class="GAT4PNUFG" __gwt_subrow="0" __gwt_row="2">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUHG">
            <td class="GAT4PNUEG GAT4PNUGG">
                <div __gwt_cell="cell-gwt-uid-324" style="outline-style:none;">
                    <span class="linkhover" title="DOB" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;color:#00A;cursor:pointer;">DOB</span>
                </div>
            </td>
            <td class="GAT4PNUEG GAT4PNUGG">
            <td class="GAT4PNUEG GAT4PNUGG">
            <td class="GAT4PNUEG GAT4PNUGG">
            <td class="GAT4PNUEG GAT4PNUGG GAT4PNUBH">
        </tr>
        <tr class="GAT4PNUEH" __gwt_subrow="0" __gwt_row="3">
            ---
        <tr class="GAT4PNUFG" __gwt_subrow="0" __gwt_row="4">       
            ---
    </tbody>
</table>
Asked By: Riaz Ladhani

||

Answers:

The XPath you currently using is quite fragile since it depends on the complete document structure and the relative position of the elements. It can easily break in the future.

Instead, locate the rows using their class or other attributes. For instance:

for row in driver.find_elements_by_css_selector("tr.GAT4PNUFG.GAT4PNUMG"):
    cell = row.find_elements_by_tag_name("td")[1]
    print(cell.text)
Answered By: alecxe

The developer has put an ID into the table. I have it working now. It is printing all the cell values from column 2. The code is:

table_id = self.driver.find_element(By.ID, 'data_configuration_feeds_ct_fields_body0')
rows = table_id.find_elements(By.TAG_NAME, "tr") # get all of the rows in the table
for row in rows:
    # Get the columns (all the column 2)        
    col = row.find_elements(By.TAG_NAME, "td")[1] #note: index start from 0, 1 is col 2
    print col.text #prints text from the element
Answered By: Riaz Ladhani

Probably a little late to this. But heres my code and works like a charm.

def find_in_table(self, name):
        check_table = self.isElementPresent("//table[@class='assessment_list_table_tableStyle__Qw-rz']",
                                            locatorType="xpath")
        while not check_table:
            time.sleep(10)
            check_table = self.isElementPresent("//table[@class='assessment_list_table_tableStyle__Qw-rz']",
                                                locatorType="xpath")

        table_id = self.driver.find_element(By.XPATH, "//table[@class='assessment_list_table_tableStyle__Qw-rz']")
        rows = table_id.find_elements(By.TAG_NAME, "tr")
        for x in range(1, len(rows)):
            col = rows[x].find_elements(By.TAG_NAME, "td")[0]
            s = col.text
            if s == name:
                return x
  1. Check whether the table exists
  2. Get the table ID with find_elements
  3. Using table ID to find the rows in table
  4. iterate through the table and finding the text in the first column
    (0)
  5. Returns the row value when text matches the one in column

XPATH of the Table Element can be obtained using the selenium plugin in IntelliJ. The plugin is so useful to find elements and more accurate than the ones in as extension in browsers.

(isElementPresent method is a method I used to check whether an element is present using seleniums getElement method and returning boolean if the element exists)

Answered By: Shahul Hameed Akmal