如果第一个XPath匹配,如何从Boolean或XPath中“中断”?

2024-04-23 07:03:02 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中使用Webdriver,我在寻找某个元素,如果找不到,我会尝试找到一个不同的元素,如果第一个元素不存在的话,通常会出现这个元素。问题是:似乎第二个XPath有时首先求值,当它返回一个有效值时,当两个元素都存在时,它不是我需要的值。在

driver.find_element_by_xpath("//ol/div[2]/div/div/div[2]/div[1]/div/div[3]/div/a[1]/div/div/div[2]/div/span | //ol/div[2]/div/div/div[2]/div[1]/div/div[3]/div/a[1]/div/div/div[2]/span").text

第一个XPath查询是我的理想场景,如果它返回一个有效的值,我需要它从OR中分离出来,这样第二个XPath就不会被计算并可能返回。或者alternativley,强制它计算第一个表达式,只有当它没有返回匹配时,它才会计算第二个表达式。我有什么选择?在

更新 下面是我想做的事情:在Google本地搜索结果页面的左边,比如this,有20个结果:

enter image description here

我想提取每个评论的得分(不是星级评分,而是评论的数量),不管它是非零,还是“没有评论”。问题是:在上面的boolean或Xpath中,它有时会获取星级,而不是评审分数:

^{pr2}$

所以我所做的是用try/except代替它:

            for result in range(1,21):
                try:
                    reviewCount = driver.find_element_by_xpath("//ol/div[2]/div/div/div[2]/div[%s]/div/div[3]/div/a[1]/div/div/div[2]/div/span" % result).text
                    reviewCounts.append(int(reviewCount.split()[0].replace(',','')))
                except:
                    #reviewCount = driver.find_element_by_xpath("//ol/div[2]/div/div/div[2]/div[%s]/div/div[3]/div/a[1]/div/div/div[2]/span" % result).text
                    reviewCounts.append(0)
            print '\t ****** Review counts for city %s : %s' % (city, reviewCounts)

但这个手术非常缓慢,通常需要2分钟(真的)。在


Tags: textdiv元素bydriver评论elementresult
3条回答

我再说一遍,我也将为您提供java代码。在

注意:这里我的“|”效果很好。我试图得到明星,如果没有明星在那里,它将返回评论的计数。我这边的输出是中文的,所以我不会把它放在这里(:(你可能认不出那是什么)。测试基于firefox。在

package com.selenium.webdriver.test;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

public class OrCondition {
    public static void main(String[] args) throws MalformedURLException {
        DesiredCapabilities capabilities = DesiredCapabilities.firefox();
        WebDriver driver = new RemoteWebDriver(new URL(
                "http://192.168.12.100:4444/wd/hub"), capabilities);
        driver.get("https://www.google.com/?gws_rd=cr,ssl&ei=t1bdVbaJKcu9eO3KhLAN&fg=1#q=chiropractors&rflfq=1&tbm=lcl&tbs=lf_msr:-1,lf:1,lf_ui:1&oll=37.10749322441741,-95.47923175&ospn=0.9812998917572173,3.251953125&oz=8&fll=36.65933277945504,-94.52342120312498&fspn=1.8859928637987977,5.16357421875&fz=8&rlfi=hd:;si:&rlha=0");
        //0. Here wait for the items load
        WebElement wait = new WebDriverWait(driver, 20)
                .until(new ExpectedCondition<WebElement>() {

                    @Override
                    public WebElement apply(WebDriver d) {
                        return d.findElement(By.className("_gt"));

                    }
                });
        long start = System.currentTimeMillis();
        //1. the same with yesterday's question.
        List<WebElement> elements = driver.findElements(By
                .xpath("//div[@class='_gt']"));

        for (int i = 0; i < elements.size(); i++) {
            WebElement e = elements.get(i);

            WebElement aTag = e.findElement(By.tagName("a"));

            // String dataCid = aTag.getAttribute("data-cid");
            //2. Use "|" 
            WebElement starSpan = aTag
                    .findElement(By
                            .xpath(".//g-review-stars/span | .//div[span[contains(text(),'reviews')]]"));

            if (starSpan.getAttribute("aria-label") != null) {
                System.out.println(starSpan.getAttribute("aria-label"));
            } else {
                System.out.println(starSpan.getText());
            }
        }

        long end = System.currentTimeMillis();
        //3. it costs about 2.5 seconds
        System.out.println("Time elapsed " + (end - start));
        driver.quit();
    }
}

XPath中的“|”运算符不是布尔运算符,或者它是一个联合运算符:它构成两个节点集的并集。所以表达式的结果包含两个选择的结果。在

我不知道driver.find_element_by_xpath()是做什么的,但我的猜测是,它以文档顺序获取XPath表达式传递的节点集中的第一个节点,这个节点可以来自union表达式的任何一个操作数。在

在XPath 2.0中解决这个问题非常容易,但我怀疑Python只提供XPath 1.0。如果是这样的话,我想最好的解决方案是Python中的一些条件逻辑。在伪代码中替换

find(A | B)

通过

^{pr2}$

我想这大概就是你在做的事情(我不懂Python),除了在X为空时强制执行一个异常。在大多数语言中,强制执行异常并捕捉异常比使用无异常逻辑要昂贵得多。在

下面是解决上述问题的java代码。(正如jeffC所说,我希望您可以将其转换为与python兼容的版本)

        List<WebElement> names=driver.findElements(By.xpath("//a[@role='link']//div[@role='heading']"));
        List<WebElement> reviews=driver.findElements(By.xpath("//a[@role='link']//span[contains(text(),'reviews') and not(@class)]"));
        int i=0;
        for(WebElement ele1:names) {
            System.out.println(ele1.getText()+"==>"+reviews.get(i).getText());
            i++
        }

输出是

^{pr2}$

相关问题 更多 >