我正在使用这样的线性布局:
现在一些线性布局有子类别,有些没有。相似的一些人有折扣,但同样没有。
所以当我做这样的事情时:
List<WebElement> allFieldsInLayout = driver.findElements(By.id("com.flipkart.android:id/product_list_product_item_layout"));
List<WebElement> allTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_main_text']"));
List<WebElement> allsubTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_sub_text']"));
List<WebElement> allOfferPricesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_price']"));
List<WebElement> allListPriceOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_mrp']"));
然后尝试在其中打印文本:
for(int i=0;i<allTitlesOnCurrentScreen.size();i++){
System.out.println("TITLE : "+allTitlesOnCurrentScreen.get(i).getAttribute("text")
+ "SUB TITLE : "+allsubTitlesOnCurrentScreen.get(i).getAttribute("text")
+ "OFFER PRICE : "+allOfferPricesOnCurrentScreen.get(i).getAttribute("text")
+ "LIST PRICE : "+allListPriceOnCurrentScreen.get(i).getAttribute("text")
);
}
我遇到了Array Out of Bound异常。所以我想如果可以从这个列表的外部布局获取所有子字段的资源ID。我试过这样:
for(int i=0;i<allFieldsInLayout.size();i++){
List<WebElement> allElementsinCurrentLayout = allFieldsInLayout.get(i).findElements(By.xpath("//android.widget.RelativeLayout[@index='2']"));
for(int j=0;j<allElementsinCurrentLayout.size();j++) {
System.out.println("Layout " + allElementsinCurrentLayout.get(j));
}
}
但它给出了例外
Cannot use xpath locator strategy from an element. It can only be used from the root element)
如果我没有相应的子标题或没有折扣,我想在我的列表中使用NULL。怎么做?
答案 0 :(得分:0)
一般来说,我处理这类问题的方法是找到包含单个产品的所有产品信息的最顶层元素。将这些元素作为集合返回并遍历它。在每次迭代中,查找包含元素的不同信息...检查是否存在并获取数据(如果存在)。此方法允许您整齐地捕获每个产品的所有属性/数据作为包。
您的方法存在的问题是您正在存储数据元素,例如:字幕,与产品分开。所以,想象一下,如果你的页面上有4个产品,只有2个产品有字幕。你循环浏览4个产品(通过索引)访问字幕......你将遇到2个问题:1)你将运行字幕数组的末尾,因为只有2,你循环到4. 2)你的字幕数组与产品数组中的产品不匹配。
想象一下这是你的页面
Product1
Subtitle1
Product2
Product3
Subtitle3
Product4
您的产品系列将包含:Product1,Product2,Product3,Product4
您的字幕数组将包含:Subtitle1,Subtitle3
因此,当您使用产品索引循环时,您将获得:
Product1, Subtitle1
Product2, Subtitle3 // notice the mismatch 2 and 3
Product3, Array out of index error
所以你跑完了字幕数组的末尾,你的字幕与相应的产品不匹配。希望这个例子更有意义......
无论如何,这是我如何做到这一点。我没有移动应用程序所以我去了flipkart.com并搜索翻盖并编写下面的代码来演示我在说什么。这个代码有效,我刚刚运行它。
public static void main(String[] args)
{
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("http://www.flipkart.com/search?q=flip+cover&as=on&as-show=on&otracker=start&as-pos=4_q_flip+cover&sid=search.flipkart.com&storePath=search.flipkart.com&type=pr&redirectToResponseURL=false&redirection=true&isMsiteTraffic=1");
List<Product> products = new ArrayList<>(); // List of Product type that will contain each product on the page
List<WebElement> productContainers = driver.findElements(By.cssSelector("div.gd-col.gu3")); // the outermost element that contains all data related to a given product
// loop through the product container elements and extract each bit of data that we care about
for (WebElement productContainer : productContainers)
{
String name = productContainer.findElement(By.cssSelector("a[data-tracking-id='prd_title']")).getText().trim();
String ratingStars = ""; // we have to initialize these variables at this scope so we can access them later outside the IF below
String NoOfRatings = ""; // NOTE: if a rating does not exist for this product, ratingStars and NoOfRatings will be empty string, ""
// these next two lines are how we determine if a piece of data exists... get the element using .findElements...
List<WebElement> ratingContainer = productContainer.findElements(By.cssSelector("div.pu-rating"));
// ... and then check to see if the list is empty
if (!ratingContainer.isEmpty())
{
// ratings exist for this product, grab the relevant data
WebElement rating = ratingContainer.get(0).findElement(By.cssSelector("div.fk-stars-small"));
ratingStars = rating.getAttribute("title"); // product rating in stars
NoOfRatings = ratingContainer.get(0).getText().trim(); // the total number of ratings, you can parse this string and extract the number, if desired
}
String finalPrice = productContainer.findElement(By.cssSelector("div.pu-final")).getText().trim(); // the price, you can extract the number, if desired
products.add(new Product(name, finalPrice, ratingStars, NoOfRatings)); // add all the relevant data into a nice, neat package just for this one product
}
// dumps the data for the products on the page
for (Product product : products)
{
System.out.println("Product: " + product.name);
System.out.println("Rating: " + product.ratingStars);
System.out.println("Number of ratings: " + product.NoOfRatings);
System.out.println("Final price: " + product.finalPrice);
System.out.println("-----------------------------");
}
}
// this class holds just 4 bits of data for each product, you can obviously add more to the class if you want to store more data
public static class Product
{
public String name;
public String finalPrice;
public String ratingStars;
public String NoOfRatings;
public Product(String name, String finalPrice, String ratingStars, String NoOfRatings)
{
this.name = name;
this.finalPrice = finalPrice;
this.ratingStars = ratingStars;
this.NoOfRatings = NoOfRatings;
}
}
输出看起来像
-----------------------------
Product: KolorEdge Flip Cover for Lenovo A6000 Plus (Black)
Rating: 3 stars
Number of ratings: (26 ratings)
Final price: Rs. 160
-----------------------------
Product: Jeelo Flip Cover for Motorola Moto G 2nd Generation (Bl...
Rating: 3 stars
Number of ratings: (128 ratings)
Final price: Rs. 137
-----------------------------
...