问题背景

最近想爬取某贝单词的词表,由于每个词表很大,某贝进行了分页,这就要求我要在获取当前页所有单词后再点击下一页,然后再获取当前页的单词,然后循环……

问题发生

获取完第一页的单词,自动单击下一页后,虽然能获得存放单词的html元素的WebElement对象,但是无法调用其getText方法(此时应该是浏览器还没把该元素的文本往上放,但是java代码的速度要比这个过程快,这时一调用getText就会导致异常,然后终止程序,特别烦)。
以下是伪代码:

     	List<String> words=new ArrayList<>();
        List<String> chinese=new ArrayList<>();
        WebElement nextPage=driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[1]/div/div/div[2]/div[2]/div[11]/div/ul/li[9]"));
        for(int i=1;i<zong;i++){
            Thread.sleep(200);

 			//下面这句就会导致上述问题。
            List<String>str=driver.findElements(By.cssSelector(".index_bottom__XLoPQ>span")).stream().map(WebElement::getText).toList();
            chinese.addAll(str);
			List<String>str2=driver.findElements(By.className("index_wordName__1lkbV")).stream().map(WebElement::getText).toList();
            words.addAll(str2);
            Thread.sleep(200);
            nextPage.click();
        }

于是我百度了下答案,但是很少有人用java来调用selenium,而且网上给出的答案都是互相抄袭,大致说的是要实现WebDriverWait类似的东西,我觉得太麻烦。也有答案是Thread.sleep,但是休眠的时间太不好控制了。

问题思考

上述可能抛出的异常,只是速度不一致导致的,这样的不一致不一定非要终止程序,我想可以这样:创建一个while(true)循环,在循环里创建一个try块,然后把容易造成不一致的代码放到try块中,然后catch,一旦catch到异常就continue,直到catch不到异常为止。当然,为了减少重复while的次数,可以在catch到异常时让线程休息一小段时间,然后再去循环。

问题解决的伪代码


      List<String> words=new ArrayList<>();
      List<String> chinese=new ArrayList<>();
      WebElement nextPage=driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[1]/div/div/div[2]/div[2]/div[11]/div/ul/li[9]"));
      List<String>str;
      List<String>str2
      for(int i=1;i<zong;i++){    
          while(true){
              try{
                  //把容易造成速度不一致的代码放try中
                  str=driver.findElements(By.cssSelector(".index_bottom__XLoPQ>span")).stream().map(WebElement::getText).toList();
                  str2=driver.findElements(By.className("index_wordName__1lkbV")).stream().map(WebElement::getText).toList();
              }catch (Exception e){
                  Thread.sleep(200);//为减少循环次数,可以稍微休息一会
                  continue;
              }
              
              //catch不到异常时
              chinese.addAll(str);
              words.addAll(str2);
              break;
          }
          nextPage.click();
      }

声明

由于catch捕捉的异常没有进行细分,所以在用该方法时,需要保证自己的代码是正确的。
大家若有更简单的方法,欢迎评论区讨论。

更多推荐

[原创]java selenium解决页面元素加载速度与获取速度不一致的问题