After Entering a string into a table with a checkbox next to it, I would like to click on the checkbox. In selenium, how can i iterate through the table and search for a particular text, then check the checkbox next to it.
Here's the html of the table:
<tbody>
<tr class="keyword-list-item">
<td width="75%">
<input class="keyword-selection-checkbox" type="checkbox" data-id="gw_78669090303"/>
<span>+spatspatulalas</span>
</td>
<td width="25%" style="text-align: right; padding-right: 4px;">
<span class="icon iconGoogle"/>
</td>
</tr>
<tr class="keyword-list-item">
<td width="75%">
<input class="keyword-selection-checkbox" type="checkbox" data-id="gw_102731166303"/>
<span>12.10 test post</span>
</td>
<td width="25%" style="text-align: right; padding-right: 4px;">
<span class="icon iconGoogle"/>
</td>
</tr>
You can use xpath for this. Just needs be little smart how you write the xpath. Notice the following xpath find the checkbox using the text of it.
String text = "12.10 test post";
By xpath = By.xpath("//span[contains(text(),'" + text + "')]/../input");
WebElement element = driver.findElement(xpath);
Related
I want to loop through the news table and get the title and rating of each row. I tried different options, but I can’t understand why the select method receives all the options at once.
I need to get each news block in a loop.
I used this way to get table link:
Elements elements = document.select("#hnmain > tbody > tr:nth-child(3) > td > table");
This query doesn't work in a loop because it gets all the elements at once. I need to get the elements sequentially. So that I can do like this:
List list = new ArrayList<>();
for (Element element: elements){
String title = element...
String rating = element...
list.add(title);
list.add(rating);
}
Sample data from html:
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr class="athing" id="33582264">
<td align="right" valign="top" class="title"><span class="rank">1.</span></td>
<td valign="top" class="votelinks">
<center>
<a id="up_33582264" href="vote?id=33582264&how=up&goto=front%3Fday%3D2022-11-13">
<div class="votearrow" title="upvote"></div></a>
</center></td>
<td class="title"><span class="titleline">Show HN: I built my own PM tool after trying Trello, Asana, ClickUp, etc.<span class="sitebit comhead"> (<span class="sitestr">upbase.io</span>)</span></span></td>
</tr>
<tr>
<td colspan="2"></td>
<td class="subtext"><span class="subline"> <span class="score" id="score_33582264">632 points</span> by tonypham <span class="age" title="2022-11-13T12:00:06">20 days ago</span> <span id="unv_33582264"></span> | hide | 456 comments </span></td>
</tr>
<tr class="spacer" style="height:5px"></tr>
<tr class="athing" id="33584941">
<td align="right" valign="top" class="title"><span class="rank">2.</span></td>
<td valign="top" class="votelinks">
<center>
<a id="up_33584941" href="vote?id=33584941&how=up&goto=front%3Fday%3D2022-11-13">
<div class="votearrow" title="upvote"></div></a>
</center></td>
<td class="title"><span class="titleline">Forking Chrome to turn HTML into SVG<span class="sitebit comhead"> (<span class="sitestr">fathy.fr</span>)</span></span></td>
</tr>
if I understand your question I think this code will work for you
Document doc = Jsoup.parse("<table border=\"0\" id=\"hnmain\" cellpadding=\"0\" cellspacing=\"0\"> <tbody> <tr class=\"athing\" id=\"33582264\"> <td align=\"right\" valign=\"top\" class=\"title\"><span class=\"rank\">1.</span></td> <td valign=\"top\" class=\"votelinks\"> <center> <a id=\"up_33582264\" href=\"vote?id=33582264&how=up&goto=front%3Fday%3D2022-11-13\"> <div class=\"votearrow\" title=\"upvote\"></div></a> </center></td> <td class=\"title\"><span class=\"titleline\">Show HN: I built my own PM tool after trying Trello, Asana, ClickUp, etc.<span class=\"sitebit comhead\"> (<span class=\"sitestr\">upbase.io</span>)</span></span></td> </tr> <tr> <td colspan=\"2\"></td> <td class=\"subtext\"><span class=\"subline\"> <span class=\"score\" id=\"score_33582264\">632 points</span> by tonypham <span class=\"age\" title=\"2022-11-13T12:00:06\">20 days ago</span> <span id=\"unv_33582264\"></span> | hide | 456 comments </span></td> </tr> <tr class=\"spacer\" style=\"height:5px\"></tr> <tr class=\"athing\" id=\"33584941\"> <td align=\"right\" valign=\"top\" class=\"title\"><span class=\"rank\">2.</span></td> <td valign=\"top\" class=\"votelinks\"> <center> <a id=\"up_33584941\" href=\"vote?id=33584941&how=up&goto=front%3Fday%3D2022-11-13\"> <div class=\"votearrow\" title=\"upvote\"></div></a> </center></td> <td class=\"title\"><span class=\"titleline\">Forking Chrome to turn HTML into SVG<span class=\"sitebit comhead\"> (<span class=\"sitestr\">fathy.fr</span>)</span></span></td> </tr>");
Elements elements = doc.select("#hnmain .athing");
for (Element element : elements) {
String title = element.select(".title").text();
String rank = element.select(".rank").text();
System.out.println(title + " -- "+rank);
}
I'm developing an Automation test using Selenium WebDriver and Java, I need to assured that there are items in the web table, and select one of those items, but the ID is dynamic.
HTML code:
<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0" style="table-layout: auto;"> <tbody>
<tr id="datagrid-row-r4-2-0" datagrid-row-index="0" class="datagrid-row datagrid-row-selected">
<td field="PLANT_CODE" style="display:none;">
<div style="text-align: left;" class="datagrid-cell datagrid-cell-c4-PLANT_CODE">1001</div>
</td>
<td field="PLANT_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-PLANT_NM">TESTE1</div>
</td>
<td field="PU_NAME" style="display:none;">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-PU_NAME"></div>
</td>
<td field="SUPPLIER_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_CODE">SUP001AR</div>
</td>
<td field="SUPPLIER_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_NM">SUPPLIER 001 AR</div>
</td>
<td field="ITEM_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ITEM_CODE">ITEM001AR</div>
</td>
<td field="ITEM_NM">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-ITEM_NM">ITEM1 AR</div>
</td>
<td field="WRHOUSNG_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-WRHOUSNG_NO"></div>
</td>
<td field="ORDE_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ORDE_NO"></div>
</td>
</tr>
<tr id="datagrid-row-r4-2-1" datagrid-row-index="1" class="datagrid-row">
<td field="PLANT_CODE" style="display:none;">
<div style="text-align: left;" class="datagrid-cell datagrid-cell-c4-PLANT_CODE">1001</div>
</td>
<td field="PLANT_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-PLANT_NM">BOCAR LERMA</div>
</td>
<td field="PU_NAME" style="display:none;">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-PU_NAME"></div>
</td>
<td field="SUPPLIER_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_CODE">SUP001AR</div>
</td>
<td field="SUPPLIER_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_NM">SUPPLIER 001 AR</div>
</td>
<td field="ITEM_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ITEM_CODE">ITEM001AR</div>
</td>
<td field="ITEM_NM">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-ITEM_NM">ITEM1 AR</div>
</td>
<td field="WRHOUSNG_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-WRHOUSNG_NO">PUR1</div>
</td>
<td field="ORDE_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ORDE_NO">PUR1</div>
</td>
</tr> </tbody> </table>
I tried "My code":
WebElement tbody = driver.findElement(By.xpath("//*[#class='datagrid-body']/tbody/tr"));
In this case, my request is returning two rows so how can I count the rows and select one of these?
Thanks
Try this step for get you want.
1. Table initialize
In your case, the table has the class datagrid-btable, the way to initialize it :
WebElement tbl = driver.findElement(By.className("datagrid-btable"));
2. Row initialize
The name tag for the web table row in general is tr, the way to initialize it :
List<WebElement> rows = tbl.findElements(By.tagName("tr"));
You can get rowCount with :
int count = rows.size();
System.out.println("count rows :" +count);
3. Column initialize
The name tag for the web table column in general are th or td, the way to initialize it :
td tag
List<WebElement> cols = rows.get(rowIndex).findElements(By.tagName("td"));
So you can select particular cell by :
String cell = cols.get(indexCol).getText();
Example for select col1 in row1 :
List<WebElement> cols = rows.get(0).findElements(By.tagName("td"));
String cell = cols.get(0).getText();
System.out.println("cell value :" +cell);
Or try this iteration for select all cell table :
for(int i=0; i<rows.size(); i++) {
//check column each in row, identification with 'td' tag
List<WebElement> cols = rows.get(i).findElements(By.tagName("td"));
//column iteration
for(int j=0; j<cols.size(); j++) {
System.out.println("row " +(i+1) +" col " +(j+1) +" : " +cols.get(j).getText());
}
}
You can get count of the rows using findElements method:
List<WebElement> rows = driver.findElements(By.cssSelector(".datagrid-btable tr.datagrid-row"));
System.out.println(rows.size());
Easy way to select row with specific text using xpath:
// get row contains text 1001
driver.findElement(By.xpath("//table[#class='datagrid-btable']//tr[#class='datagrid-row' and contains(.,'1001')]")).click();
// get row by PLANT_CODE and exact cell value
driver.findElement(By.xpath("//table[#class='datagrid-btable']//tr[#class='datagrid-row' and .//td[#field='PLANT_CODE' and div[text()='1001']]]")).click();
To find row you need, you can use stream().filter(). In the example below, rows filtered by PLANT_NM text. Using filter or rows iteration, you can write a method to filter rows by any/multi cells:
List<WebElement> rows = driver.findElements(By.cssSelector(".datagrid-btable tr.datagrid-row"));
System.out.println(rows.size());
List<WebElement> filteredRows = rows.stream().filter(element ->
element.findElement(By.cssSelector("td[field='PLANT_NM'")).getText().equals("BOCAR LERMA"))
.collect(Collectors.toList());
Assert.assertTrue(filteredRows.size() > 0, "Row with \"BOCAR LERMA\" PLANT_NM exist.");
filteredRows.get(0).click();
I was trying to figure out a way to check the checkboxes in the table grid. Usually they are defined as type='checkbox'. So I'm finding it difficult to implement using the webDriver to check the checkboxes since they are in the tags.
A sample HTML code is given below.
<tbody id="gridview-2345-body">
<tr id="gridview-2345-record-/DNA/Study1_HS.xml" class="x4-grid-row x4-grid-data-row x4-grid-row-selected" data-boundview="gridview-1270" role="row">
<td id="ext4-ext-gen1234" class="x4-grid-cell x4-grid-td" role="gridcell">
<div class="x4-grid-cell-inner " style="text-align:left;" unselectable="on">
<div class="x4-grid-row-checker"/>
</div>
</td>
<td id="ext4-ext-1235" class="x4-grid-cell x4-grid-td" role="gridcell">
<div class="x4-grid-cell-inner " style="text-align:left;" unselectable="on">
<span id="ext4-icon1568" class="fa fa-file-code-o labkey-file-icon"/>
</div>
</td>
<td id="ext4-ext-gen1236" class="x4-grid-cell x4-grid-td" role="gridcell">
<div class="x4-grid-cell-inner " style="text-align:left;" unselectable="on">
<div width="100%" height="16px">
<div style="float: left;"/>
<div style="padding-left: 8px; white-space:normal !important;">
<span style="display: inline-block; white-space: nowrap;">Study1_HS.xml</span>
</div>
</div>
</div>
</td>
</tr>
</tbody>
I tried using 'contains' in the xpath
driver.findElement(By.xpath("//*[contains(#id, 'Study1_HS.xml')]/td[1]/div/div")).click();
I'm wondering... since the TR contains the class change when the checkbox is checked, maybe clicking the TR will trigger the check. Try this and see.
String searchText = "Study1_HS.xml";
List<WebElement> rows = driver.findElements(By.tagName("tr"));
for (WebElement row : rows)
{
if (row.getText().contains(searchText))
{
row.click();
break;
}
}
So I used 'preceding' in the xpath to make it work
//span[text()='Study1_HS.xml']/preceding::td/div/div[#class='x4-grid-row-checker']
http://www.xpathtester.com/xpath/b1d50008dd4be8ab7545548c4b8238f5
I am trying to scrape with selenium a table of products.
Here is my example table:
<div class="article">
<table style="width: 100%">
<tbody><tr>
<td class="trenner_u"></td>
<td class="trenner_u">
<a href="/details/12900101" class="changeable">
<span>Product 1 </span>
</a>
</td>
<td class="trenner_lu">
11.11.1999
</td>
<td class="trenner_lu">
<a title="Category Product Group" href="/grp/detailsSmallTB_iframe=true&height=132&width=420" class="thickbox">Group 1</a>
</td>
<td class="trenner_lu">
1999$
</td>
</tr>
<tr>
<td class="trenner_u"></td>
<td class="trenner_u">
<a href="/details/12900347" class="changeable">
<span>Product 2 </span>
</a>
</td>
<td class="trenner_lu">
1.12.1944
</td>
<td class="trenner_lu">
<a title="Category Product Group" href="/grp/detailsSmallTB_iframe=true&height=132&width=420" class="thickbox">Group 2</a>
</td>
<td class="trenner_lu">
1234$
</td>
</tr>
<tr>
<td class="trenner_u"></td>
<td class="trenner_u">
<a href="/details/12908635" class="changeable">
<img class="positionable" src="/ImageImage/12908635" alt="" style="width: 100px; opacity: 0.9;">
<span>Product 1 </span>
<img src="/Content/images/icons/photo.png" alt="Foto">
</a>
</td>
<td class="trenner_lu">
05.12.1950
</td>
<td class="trenner_lu">
<a title="Category Product Group" href="/grp/detailsSmallTB_iframe=true&height=132&width=420" class="thickbox">Group 2</a>
,<a title="Category Product Group" href="/grp/detailsSmallTB_iframe=true&height=132&width=420" class="thickbox">Group 4</a>
</td>
<td class="trenner_lu">
131282$
</td>
</tr>
</tbody></table>
</div>
I tried to scrape each element with:
List<WebElement> links = driver.findElements(By.xpath("//*[#id=\"home\"]/div[3]/table/tbody/tr/td[2]/a"));
List<WebElement> prodNames = driver.findElements(By.xpath("//*[#id=\"home\"]/div[3]/table/tbody/tr/td[2]/a"));
List<WebElement> group = driver.findElements(By.xpath("//*[#id=\"home\"]/div[3]/table/tbody/tr/td[4]/a"));
However, as you can see one of my td elements has two links inside, therefore my WebElement list has not the same length and it is extremely hard to merge together.
My desired list output should look like that:
[Product 1, 11.11.1999, Group 1, 1999$], [Product 2, 1.12.1944,Group 2, 1234$], [Product 1, 05.12.1950, Group 2 Group 2, 131282$]
Any suggestion how to scrape such a table much more efficient?
I appreciate your replies!
Think about everything you interact with as of objects:
class Table {
private static final String TABLE_CELL = "//table/tbody/tr[%d]/td[%d]";
public String getTableCellText(int row, int col) {
WebElement cell = driver.findElement(By.xpath(String.format(TABLE_CELL, row, col)));
return cell.getText();
}
}
You can use it as you see fit:
Table t = new Table();
System.out.println(t.getTableCellText(3, 5)); // prints 131282$
You could probably iterate through each row to make it clearer as to what you are doing in python it would be:
rows = driver.find_elements(By.XPATH, "//*[#id=\"home\"]/div[3]/table/tbody/tr")
for row in rows:
cells = row.find_elements(By.XPATH, "//td")
product_name = cells[1].text
... etc ...
I have a website that contains a table that look like similar(bigger..) to this one:
</table>
<tr>
<td>
<table width="100%" cellspacing="-1" cellpadding="0" border="0" dir="rtl" style="padding-top: 25px;">
<tr>
<td align="right" style="padding-right: 25px;">
<span class="artist_name_txt">
name
<p class="diccografia">subname</p>
</span>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table width="100%" border="0" cellspacing="0" cellpadding="0" dir="rtl" style="padding-right: 25px; padding-left: 25px">
<tr>
<td class="songs" align="right">
number1
</td>
</tr>
<tr>
<td class="songs" align="right">
number2
.......
</td>
</tr>
</table>
and I need an idea how can i parse the website and extract this table into 2 arrays -
one will be something like names{number1, number2}
and the second will be links{number1link, number2link}
I tried a lot of ways and nothing really helps me.
You should read the JSoup Cookbook - especially the Selector syntax is very powerful.
Here's an example:
final String html = ...
// use connect().get() instead if you connect to an website
Document doc = Jsoup.parse(html);
List<String> names = new ArrayList<>();
List<String> links = new ArrayList<>();
for( Element element : doc.select("a.artist_player_songlist") )
{
names.add(element.text());
links.add(element.attr("href"));
}
System.out.println("Names: " + names);
System.out.println("Links: " + links);
Output:
Names: [number1, number2]
Links: [/number1link, /number2link]
Android Web Scraping with a Headless Browser
Htmlunit on Android application
HttpUnit/HtmlUnit equivalent for android