基于selenium实现动态爬取页面(java)


参考文章:https://blog.csdn.net/qq_22003641/article/details/79137327?spm=1001.2014.3001.5506

前言

使用selenium进行爬虫,需要下载相关浏览器的驱动程序,和添加selenium相关的jar包。
浏览器驱动程序地址:

selenium相关依赖:

	<dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.4.0</version>
    </dependency>

jar包下载地址:https://mvnrepository.com/

一、Selenium是什么?

Selenium是一个用于web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。Selenium完全开源,对商业用户也没有任何限制,支持分布式,拥有成熟的社区与学习文档。使用Selenium实现爬虫最大的好处在于能够模拟一个用户正常访问页面,网站后台不容易检测出来,而且使用简单,可以使用java或python等多种编程语言编写用例脚本。

二、Selenium常见的API

1.Selenium定位的方法

Selenium提供了8种定位方式,这些方式在Java中所对应的方法如下:

  • id-------------------------------------------------------------findElement(By.id())
  • name--------------------------------------------------------findElement(By.name())
  • class name------------------------------------------------findElement(By.className())
  • tag name--------------------------------------------------findElement(By.tagName())
  • link text----------------------------------------------------findElement(By.linkText())
  • partial link text-------------------------------------------findElement(By.partialLinkText())
  • xpath-------------------------------------------------------findElement(By.xpath())
  • css selector----------------------------------------------findElement(By.cssSelector())

具体使用例子:

<html>
  <head></head>
  <body link="#0000cc">
    <a id="result_logo" href="/" onmousedown="return c({ 
        'fm':'tab','tab':'logo'})">
    <form id="form" class="fm" name="f" action="/s">
      <span class="soutu-btn"></span>
        <input id="kw" class="s_ipt" name="wd" value="" maxlength="255" autocomplete="off">
    </form>
    <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
   </body>
 </html>
driver.findElement(By.id("kw"));//通过id定位的方式定位到input标签上面。
driver.findElement(By.name("wd"));//通过name定位方式定位到input标签上面。
driver.findElement(By.className("s_ipt"));//通过class name定位到input标签上面。
driver.findElement(By.tagName("input"))//通过tag name定位到input标签上面。
driver.findElement(By.xpath("//*[@id='kw']"));//通过xpath定位到input标签上面。
driver.findElement(By.cssSelector("#kw");//通过css定位到input标签上面。
driver.findElement(By.linkText("新闻");//通过link text定位到a标签上面。
driver.findElement(By.partialLinkText("新");//通过partialLink text定位到a标签上面。

提示:鼠标对准元素右键 > 检查 > 对准标签右键 > 点击copy,即可直接复制通过xpath或css等定位方式的路径。

2.控制浏览器窗口大小

  • maximize() 设置浏览器最大化
  • setSize() 设置浏览器宽高
    例子:讲浏览器窗口的大小设置成(500*800)
    driver.manage().window().setSize(new Dimension(480, 800));

3.控制浏览器后退、前进

在使用浏览器浏览网页时,浏览器提供了后退和前进按钮,可以方便地在浏览过的网页之间切换,WebDriver也提供了对应的back()和forward()方法来模拟后退和前进按钮。下面通过例子来演示这两个方法的使用。

  • back() 模拟浏览器后退按钮
  • forward() 模拟浏览器前进按钮
    driver.navigate().back();
    driver.navigate().forward();

4.刷新页面

有时候需要手动刷新(F5) 页面。

  • refresh() 刷新页面(F5)
driver.navigate().refresh();

三、WebDriver常用方法

方法 含义
clear() 清除文本
sendKeys(*value) 模拟按键输入
click() 单击元素
submit() 提交表单
getSize() 返回元素的尺寸
getText() 获取元素的文本
getAttribute(name) 获得属性值
isDisplayed() 设置该元素是否用户可见

四、模拟鼠标的操作

方法 含义
contextClick() 右击
clickAndHold() 鼠标点击并控制
doubleClick() 双击
dragAndDrop() 拖动
release() 释放鼠标
perform() 执行所有Actions中存储的行为

五、模拟键盘操作

Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, sendKeys()方法可以用来模拟键盘输入, 除此之 外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等。
例子:

	input.sendKeys(Keys.SPACE);
    input.sendKeys("教程");
    Thread.sleep(2000);
 
    input.sendKeys(Keys.CONTROL,"a");
    Thread.sleep(2000);

六、获取断言信息

方法 含义
getTitle() 用于获得当前页面的title
getCurrentUrl() 用户获得当前页面的URL
getText() 获取页面文本信息

七、设置元素等待

WebDriver提供了两种类型的等待:显式等待和隐式等待。

显示等待

WebDriverWait类是由WebDirver提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。具体格式如下:
WebDriverWait(driver, 10, 1)
driver: 浏览器驱动。 10: 最长超时时间, 默认以秒为单位。 1: 检测的的间隔(步长) 时间, 默认为 0.5s。

 public static void main(String[]args) throws InterruptedException {
    
    
 
    WebDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
 
    //显式等待, 针对某个元素等待
    WebDriverWait wait = new WebDriverWait(driver,10,1);
 
    wait.until(new ExpectedCondition<WebElement>(){
    
    
      @Override
      public WebElement apply(WebDriver text) {
    
    
            return text.findElement(By.id("kw"));
          }
    }).sendKeys("selenium");
 
    driver.findElement(By.id("su")).click();
    Thread.sleep(2000);
 
    driver.quit();
  }

隐式等待

方法 含义
implicitlyWait() 识别对象时的超时时间。过了这个时间如果对象还没找到的话就会抛出NoSuchElement异常
setScriptTimeout 异步脚本的超时时间。WebDriver可以异步执行脚本,这个是设置异步执行脚本脚本返回结果的超时时间
pageLoadTimeout 页面加载时的超时时间。因为WebDriver会等页面加载完毕再进行后面的操作,所以如果页面超过设置时间依然没有加载完成,那么WebDriver就会抛出异常。

八、多表单切换

  • driver.switchTo().frame(xf),xf为另一个表单的元素。
	WebElement xf = driver.findElement(By.xpath("//*[@id='loginDiv']/iframe"));
    driver.switchTo().frame(xf);

九、多窗口切换

  • switchTo().window()
  • getWindowHandle(): 获得当前窗口句柄。
  • getWindowHandles(): 返回的所有窗口的句柄到当前会话。
  • switchTo().window():用于切换到相应的窗口,与上一节的switchTo().frame()类似,前者用于不同窗口的切换, 后者用于不同表单之间的切换。
	driver.switchTo().window(handle);

十、下拉框选择

<select id="nr" name="NR">
  <option value="10" selected>每页显示 10 条</option>
  <option value="20">每页显示 20 条</option>
  <option value="50">每页显示 50 条</option>
<select>
  public static void main(String[] args) throws InterruptedException {
    
    
 
    WebDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
 
    driver.findElement(By.linkText("设置")).click();
    driver.findElement(By.linkText("搜索设置")).click();
    Thread.sleep(2000);
 
    //<select>标签的下拉框选择
    WebElement el = driver.findElement(By.xpath("//select"));
    Select sel = new Select(el);
    sel.selectByValue("20");
    Thread.sleep(2000);
 
    driver.quit();
  }

十一、警告框处理

  • getText(): 返回 alert/confirm/prompt 中的文字信息。
  • accept(): 接受现有警告框。
  • dismiss(): 解散现有警告框。
  • sendKeys(keysToSend): 发送文本至警告框。
  • keysToSend:将文本发送至警告框。
public static void main(String[] args) throws InterruptedException {
    
    
 
    WebDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
 
    driver.findElement(By.linkText("设置")).click();
    driver.findElement(By.linkText("搜索设置")).click();
    Thread.sleep(2000);
 
    //保存设置
    driver.findElement(By.className("prefpanelgo")).click();
 
    //接收弹窗
    driver.switchTo().alert().accept();
    Thread.sleep(2000);
 
    driver.quit();
  }

十二、浏览器cookie操作

  • getCookies() 获得所有 cookie 信息。
  • getCookieNamed(String name) 返回字典的key为“name”的Cookie信息。
  • addCookie(cookie dict) 添加Cookie。“cookie_dict”指字典对象,必须有 name和value值。
  • deleteCookieNamed(String name) 删除Cookie 信息。 “name”是要删除的 cookie的名称;“optionsString” 是该Cookie的选项,目前支持的选项包括“路径” , “域” 。
  • deleteAllCookies() 删除所有 cookie 信息。
public static void main(String[] args){
    
    
 
    WebDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
 
    Cookie c1 = new Cookie("name", "key-aaaaaaa");
    Cookie c2 = new Cookie("value", "value-bbbbbb");
    driver.manage().addCookie(c1);
    driver.manage().addCookie(c2);
 
    //获得 cookie
    Set<Cookie> coo = driver.manage().getCookies();
    System.out.println(coo);
 
    //删除所有 cookie
    //driver.manage().deleteAllCookies();
 
    driver.quit();
  }

十三、调用JavaScript代码

虽然WebDriver提供了操作浏览器的前进和后退方法,但对于浏览器滚动条并没有提供相应的操作方法。在这种情况下,就可以借助JavaScript来控制浏览器的滚动条。WebDriver提供了executeScript()方法来执行JavaScript代码。

 public static void main(String[] args) throws InterruptedException{
    
    
 
    WebDriver driver = new ChromeDriver();
    //设置浏览器窗口大小
    driver.manage().window().setSize(new Dimension(700, 600));
    driver.get("https://www.baidu.com");

    //进行百度搜索
    driver.findElement(By.id("kw")).sendKeys("webdriver api");
    driver.findElement(By.id("su")).click();
    Thread.sleep(2000);
 
    //将页面滚动条拖到底部
    ((JavascriptExecutor)driver).executeScript("window.scrollTo(100,450);");
    Thread.sleep(3000);
    driver.quit();
  }

注意事项

  • 下载浏览器驱动程序时,尽量与自己电脑的浏览器版本一致或相近。

其实我也不知道为什么要这样,理论上来说下载的驱动程序应该不与电脑本身的浏览器有联系,但之前在爬虫时遇到一些问题,上网搜一下,基本上都是说驱动程序版本不一致。为了快速的实现功能,还是下载对应的版本驱动程序吧,避免后面出现问题。

猜你喜欢

转载自blog.csdn.net/weixin_45893787/article/details/124535153