`
m635674608
  • 浏览: 4905904 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Java中如何利用Selenium获取元素分析网页内容

    博客分类:
  • java
 
阅读更多

本文首先探讨了编写 Selenium 脚本时的两种最简单、常用的截图方法,接着重点介绍了在难以利用普通截图方法获取到截图时,如何利用 Selenium 获取到的元素分析网页内容,进而绘制出所需要的图像的方法。

翻译验证测试 (Translation Verification Test) 是全球化测试的重要组成部分。在翻译验证测试准备阶段,翻译验证测试技术支持人员经常需要截取大量的图片给各个国家的测试人员。为了节省时间,实现自动化截图已是大势所趋。一般情况下,我们直接使用 Selenium 的 getScreenshotAs() 方法就可以满足多数情况下的需要。然而,该方法对很多悬浮框和下拉菜单的处理却不尽人意。接下来让我们一起来看看在实际应用中我们都可以选择哪些方法。

一、利用 Selenium 的 getScreenshotAs() 方法

利用 TakesScreenshot 接口提供的 getScreenshotAs() 方法捕捉屏幕,是我们在开发 Selenium 脚本时最常用的方法。getScreenshotAs() 函数可以返回 BASE64、BYTES 或 FILE 类型的数据。当指定返回类型为 BASE64 的时候 ,会返回一个 base64 编码字符串;当指定返回类型为 BYTES 的时候,会返回一个 bytes 数组; 当指定返回类型为 FILE 的时候,会将获取到的截图存放到一个临时文件中,以供复制到指定的文件。该方法可以满足最基本的需求。如清单 1 所示, captureScreen() 方法会将整个屏幕截下来,并将图片保存为 jpg 文件。

清单 1. 利用 Selenium 自带的方法截图

public static void captureScreen(WebDriver driver,String screenName) throws IOException{
	//判断是否存在screenpath目录
	if(!(new File(screenpath).isDirectory())){  
        new File(screenpath).mkdir();  
    }
	File screenShotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);  
    FileUtils.copyFile(screenShotFile, new File(screenpath+screenName+".jpg"));	    
}

Selenium 的 getScreenshotAs() 方法并不能处理一些更为复杂的问题,如对某些悬浮框、下拉菜单选项进行截图时,该方法返回的图片中并不包含悬浮框、下拉菜单部分。此时,可以选择采用 Robot 类的 createScreenCapture() 方法。

二、利用 Robot 类的 createScreenCapture() 方法

利用 Java 的 Robot 类可以完成一些与操作系统有关的底层输入,通过 Robot 类的 createScreenCapture() 方法可以截取到和 PrtSc 按键相同效果的图片。该方法简单易用,且功能强大,基本可以满足大部分需求。

清单 2. 利用 Robot 截图

public static void captureScreen(String screenName, int x, int y,
		int width, int height) {
	try {
		BufferedImage capture = null;
		Rectangle area = new Rectangle(x, y, width, height);
		Robot robot = new Robot();
		capture = robot.createScreenCapture(area);
		String fn = screenpath + screenName + ".jpg";
		FileOutputStream out = new FileOutputStream(fn);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
		encoder.encode(capture);
		out.flush();
		out.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

对于某些气泡悬浮框,如 title 属性值,需要将鼠标悬浮在元素上才可以显示出来。采用 Selenium 的 Actions 类去模拟鼠标操作,可以解决一些通过 javascript、css 控制的鼠标移动、悬浮操作 ,但是对于 title 这样的气泡悬浮框却无能为力,因为 Actions 方法只是模拟鼠标操作,而 title 属性值需要在真实的鼠标悬浮在元素上时才会显示出来。此时,可以先使用 Robot 类的 mouseMove() 方法将鼠标移到指定屏幕位置,再进行截图。

清单 3. 在 Robot 类的 mouseMove() 方法中应用 Selenium 获取到的点坐标

Robot robot = newRobot(); 
Point point = element.getLocation(); 
robot.mouseMove(point.x+55, point.y+90);

mouseMove() 中的点坐标为 Selenium 获取到的元素的屏幕坐标,而通过 getLocation() 方法获得的元素坐标为元素相对于浏览器内的 document 对象的坐标,所以需要进行微调。

由于 Robot 类操作的是一些操作系统事件,所以在某些系统(如 X-Window 系统)中如果 Robot 类访问鼠标、键盘的操作需要特定权限,那么可能会抛出 AWTException。然而,在多平台上实现截图并不是我们在本文中需要考虑的内容。利用 Robot 类的截图方法可以截取指定区域的屏幕,相比第一种方法更加灵活,功能也更加强大。

三、解析网页页面,动态生成图片

对于页面中某些气泡悬浮框(如图 1 中的“到百度首页”字符串),如 title 和 alt 属性值,虽然使用 Robot 可以截取到,但是需要调节坐标位置。在我们实际应用中,由于我们一般都是通过 Remote Desktop Connection Manager 连接多台远程虚拟机,屏幕的大小有时会发生改变,因而元素的坐标位置也经常需要调节。

图 1. 气泡悬浮框示例

图 1. 气泡悬浮框示例

实现思路

所以对于此类情况,我们可以通过另外一种方式解决,即解析网页页面,取出 title 属性值,并根据 title 信息绘制成图片,最后将绘制好的图片添加到原来的图中并返回整张图片。从理论上讲,所有的页面元素,我们都可以通过此方法实现截图。实现方法如清单 4 所示。

清单 4. 抓取完整的屏幕截图

public static void captureFlyover(WebDriver driver,String xpath,String screenName) throws Exception{
    BufferedImage img;
    BufferedImage img1;
    //img1为抓取的不包含tooltip的屏幕截图
    img1 = gsscScreenshotImage(driver);
    //img为将悬浮框添加到img1后返回的屏幕截图
	img = gsscAddTooltip(driver.findElement(By.xpath(xpath)), img1);
	ImageIO.write(img, "png", new File(screenpath+screenName+".jpg"));
}

其中, gsscScreenshotImage() 方法调用的是第一种方式中的 getScreenshotAs() 方法。接着,我们来看一下 gsscAddTooltip() 的实现方式。我们首先在 gsscCreateTooltip() 创建了 tooltip 图像。根据传入的 Selenium 获取到的 element 对象,我们可以获取到元素的 title 和 font-family 等属性值以及元素的坐标位置。根据这些信息,我们创建出一个 img 图像。我们将图像的背景色设置为 #F5FCDE。但为了更加逼真,我们还可以通过 getCssValue() 方法获取到更多和元素有关的信息,如 background、border、padding 等等。

清单 5. 创建悬浮框

public static Point text_location;
	
//获取title属性值,创建tooltip
public static BufferedImage gsscCreateTooltip (WebElement element, int size) throws Exception{
	
	String text = element.getAttribute("title");
	String text_font = element.getCssValue("font-family");
	text_location = element.getLocation();
	int tooltip_h = size+7;
	
	BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
	Graphics2D tooltip = img.createGraphics();
        //设置悬浮框的宽度为文本的宽度加上7像素
	int tooltip_w = tooltip.getFontMetrics().stringWidth(text)+7;
	img = new BufferedImage(tooltip_w, tooltip_h, BufferedImage.TYPE_INT_ARGB);
	tooltip = img.createGraphics();
	//将创建图像的文字字体设置为从页面元素中获取到的文字字体
	tooltip.setFont(new Font(text_font, Font.PLAIN, size));
	tooltip.setPaint(Color.decode("#F5FCDE"));
	tooltip.fillRect(0, 0, tooltip_w, tooltip_h);
	tooltip.setPaint(Color.black);
	tooltip.draw3DRect(0, 0, tooltip_w-1, tooltip_h-1, true);
        //将文本绘制到图像上,drawString()并不支持文本的自动换行,当需打印的文                         
        //本太长时,需要自己实现自动换行
	tooltip.drawString(text,3,tooltip_h-5);
	tooltip.dispose();
	return img;
}


然后,我们在 gsscAddTooltip() 中进行判断,如果我们只想得到仅包含 tooltip 的图片,那么我们直接利用 tooltip 这个 BufferedImage 对象绘出图像并返回。否则将 tooltip 绘制在 img 中指定元素的坐标位置附近(以元素中心为坐标,向 x 和 y 方向分别偏移 20px)。

清单 6. 将悬浮框添加到 Selenium 截取的图片中

public static BufferedImage gsscAddTooltip (WebElement element, BufferedImage img) throws Exception{	
	// 创建tooltip
	BufferedImage tooltip = gsscCreateTooltip(element, 12);
	int tooltip_w = tooltip.getWidth();
	int tooltip_h = tooltip.getHeight();
	BufferedImage buffImg;
	Graphics2D graphic;
	
	if (img != null){
		// 将tooltip添加到img中
		int img_w = img.getWidth();
		int img_h = img.getHeight();
		
		if (img_w >= (tooltip_w+text_location.getX())){
			buffImg = new BufferedImage(img_w, img_h+tooltip_h+2, BufferedImage.TYPE_INT_ARGB);
		}else{
		buffImg = new BufferedImage(tooltip_w+text_location.getX()+10, img_h+tooltip_h+2, BufferedImage.TYPE_INT_ARGB);
		}
		graphic = buffImg.createGraphics();
		graphic.drawImage(img, 0, 0, null);
		graphic.drawImage(tooltip, text_location.x+20, text_location.y+20, null);
	}else{
		buffImg = new BufferedImage(tooltip_w+3, tooltip_h+2, BufferedImage.TYPE_INT_ARGB);
		graphic = buffImg.createGraphics();
		graphic.drawImage(tooltip, 3, 1, null);
	}
	graphic.dispose();
	return buffImg;
}

图 2. 利用第三种方式截到的图(仅显示部分)

图 2. 利用第三种方式截到的图(仅显示部分)

需要注意的问题

利 用该方法截取百度页面(http://www.baidu.com/s?wd=mytest&rsv_bp=0&ch=& tn=baidu&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=1& inputT=7063)中的百度 logo 的 title“到百度首页”这个字符串的时候,截到的却是乱码。利用 FireBug 查看该网页的源代码才发现,原来该元素的字体被设置成了 arial。当页面文字被设置成某些西方字体如 arial 这样的字体时,调用 drawString() 方法打印中文字符会出现乱码。这时,只要将字体改为某些支持的字体就可以了,如:tooltip.setFont(newFont("宋体", Font.PLAIN, size));

图 3. 百度搜索结果页面的字体

图 3. 百度搜索结果页面的字体

图 4. 修改字体前后截图对比(仅显示部分)

图 4. 修改字体前后截图对比(仅显示部分)

对动态生成图片方法的改进

在 captureFlyover() 函数中,页面指定元素是通过 xpath 来获取的,该实例只返回了一个页面元素。如有需要,可以根据 xpath 表达式获取到所有符合条件的页面元素,然后将这些页面元素逐一添加到截图中,从而实现在同一个页面中获取到多个悬浮框的效果。但这种方法面临的另一个问题就是,多个悬浮框有可能会重叠,需要注意每个悬浮框在截图中显示的具体位置。

清单 7. 利用 xpath 获取多个页面元素

 //driver.findElements(By.xpath(xpath)会返回符合xpath表达式的所有元素,而 
 //driver.findElement(By.xpath(xpath)会返回符合xpath表达式的第一个元素
 img = gsscAddTooltips(driver.findElements(By.xpath(xpath)), img1);

通过解析网页动态生成图片,需要编写比较多的代码,实现难度相对比较大,一般只有在需要大量的截取某同类型的图片且无法通过 getScreenshotAs() 方法实现时才会选择。

结束语

本文通过示例代码,介绍了在用 Selenium 进行自动化测试时可以选用的三种网页截图方法。三种方法,各有优劣,可以适用在不同场景。读者也可以利用 JNI,通过调用第三方组件的方式来实现网页截图。但由于我们对性能并没有太高的要求,所以在实际应用中并未采用这种做法,这里也不再多述。

http://www.ithov.com/linux/131668_2.shtml

分享到:
评论

相关推荐

    selenium获取元素信息的方法.docx

    selenium获取元素信息的方法,UI,提示信息

    java自动化操作win窗口元素

    selenium无法操作win窗口元素,例如附件上传等,RobotFramework框架中自带了AutoItLibrary扩展库,可以很好的操作这些元素,但用java结合selenium来自动化测试时,并没有已经封装的类库,但是可以借助autoit和jacob...

    41_41_使用Selenium获取页面元素的方法.mp4

    java

    Appium_selenium_java_getListItem

    Appium_selenium_java: 获取处理android listview、ScrollView、recyclerview 等 list item控件下子元素遍历方法

    python实现windows自动化(webdriver+WinAppDriver+inspect.exe)(csdn.pdf

    python实现windows自动化(webdriver+WinAppDriver+inspect.exe)(csdn

    Selenium_Java_Collection

    Selenium_Java_Collection 打开网址: : (请勿登录),并通过检查标题和页面定位器来验证是否打开了页面。 搜索电视并查看搜索结果。 获取所有产品名称和价格,将其保存在哈希表集合中,键为产品名称,值作为价格。...

    IE浏览器Xpath工具.zip

    主要用于自动化测试中IE浏览器下获取元素的XPath,经过测试,结果和chrome生成的一样,使用java,或python+selenium定位元素

    硒页面对象发电机「Selenium Page Object Generator」-crx插件

    tel和url输入类型*添加其他方法以更可靠地获取元素文本*添加对不带标识符的标签的支持*添加对带前缀元素类型的支持*添加恢复到出厂设置*为支持此功能的测试框架添加AngularJS locators选项*添加选项以限制要从中生成...

    Katalon_Studio_Windows_64-7.5.5.zip

    katalon:基于web方向的自动化测试工具(快速捕获页面元素,并生成相应测试脚本),整体基于selenium和Appium框架,Studio提供了内置数百个关键字的预定义自动化框架。 相比已python+selenium自己搭建测试环境,不...

    Python入门网络爬虫之精华版

    抓取之后就是对抓取的内容进行分析,你需要什么内容,就从中提炼出相关的内容来。 常见的分析工具有正则表达式,BeautifulSoup,lxml等等。 存储 分析出我们需要的内容之后,接下来就是存储了。 我们可以选择存入...

    软件测试自动化工程

    selenium+java+tesng+maven测试框架,点击,输入,智能等待页面加载,智能获取元素值。执行失败截图,查看reportng测试报告,错误日志。

    phantomjs1.9.8历史版本用于爬虫

    //开始打开网页,等待输入元素出现 Document document = Jsoup.parse(webDriver.getPageSource());  //TODO 剩下页面的获取就按照Jsoup获取方式来做  }finally{  if (webDriver != null) {  webDriver.quit()...

    XPath Finder & Test Recorder by Tesrupt-crx插件

    -在Robot Framework,Selenium Java,Selenium TestNG和Selenium Python测试框架中实时生成测试脚本。 (更多框架即将推出)-拖动以重新排序测试中的步骤。 -点击删除即可删除不想要的或意外添加的步骤。 -现在,您...

    LetXPath-crx插件

    语言:English LetXPath-XPath Finder,简单有用的开源项目 LetXPath是一个开放源代码项目,它只需单击... LetXPath支持自现在Selenium-Java,Selenium-Python,Selenium-C#和Protractor JS3。Custome框架处于开发阶段

Global site tag (gtag.js) - Google Analytics