Selenium PhantomJS 等待图像可用
Selenium PhantomJS wait for image to be available
我正在编写一个通用的基于 selenium phantomjs 的蜘蛛来访问和抓取网页。
程序的输入包括需要抓取的模板(css选择器),输出应该根据模板产生数据。
如果我们尝试从网站抓取图片,有时我们可能会得到空图片(如果执行时的页面源不包含图片,就会出现这种情况),这可以通过 wait 解决
然而,当网页为图像提供占位符时,会出现更具挑战性的问题,这些占位符稍后会通过 ajax
请求被真实图像 URL 替换。
问题是,如何确保 selenium 只在页面中包含真正的 URL 图像后才抓取图像。我正在考虑检查图像的 src
属性是否有更改,只有在一次更改后我才应该开始解析页面源代码。但是,不确定如何实施?或者这是一个好主意吗?
编辑
<html>
<head>
<style>
img {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<div id='wrapper'>
<div class='wrapper-child'>
<img data-backup='./1clr.jpg' src='./1bw.jpg'>
</div>
<div class='wrapper-child'>
<img data-backup='./2clr.jpg' src='./2bw.jpg'>
</div>
<div class='wrapper-child'>
<img data-backup='./3clr.jpg' src='./3bw.jpg'>
</div>
</div>
<script src='./jquery.js'></script>
<script type='text/javascript'>
$(document).ready(function() {
// setTimeout(function() {
//replace image placeholders
$.get("ajax/test.html", function(data) {
}).always(function() {
$('img').each(function() {
$(this).attr('src', $(this).attr('data-backup'));
});
});
// }, 1000);
});
</script>
</body>
</html>
假设我有这个页面,在 jquery 更新后如何使用 selenium 抓取图像?
如果该站点正在使用 jQuery,您可以检查以下内容以确保所有 ajax 交互都已完成。
jQuery.active == 0
检查此线程是否有相关问题:wait for an ajax call to complete with Selenium 2 web driver
编辑
此代码适用于我们:
public static int TIME_OUT_SECONDS = 10;
public static int POLLING_MILLISECONDS = 100;
public static final String JS_JQUERY_DEFINED = "return typeof jQuery != 'undefined';";
public static final String JS_JQUERY_ACTIVE = "return jQuery.active != 0;";
public static final String JS_DOC_READY = "return document.readyState != 'complete';";
public static final String JS_BLOCK = "return typeof $ != 'undefined' && typeof $.blockSelenium != 'undefined' && $.blockSelenium==true;";
public static void waitForJQuery(final WebDriver driver) {
new FluentWait<WebDriver>(driver).withTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS).pollingEvery(POLLING_MILLISECONDS, TimeUnit.MILLISECONDS).until(new Function<WebDriver, Boolean>() {
@Override
public Boolean apply(final WebDriver input) {
boolean ajax = false;
boolean jQueryDefined = executeBooleanJavascript(input, JS_JQUERY_DEFINED);
if (jQueryDefined) {
ajax |= executeBooleanJavascript(input, JS_JQUERY_ACTIVE);
}
boolean ready = executeBooleanJavascript(input, JS_DOC_READY);
boolean block = executeBooleanJavascript(input, JS_BLOCK);
ajax |= ready;
ajax |= block;
// continue if all ajax request are processed
return !ajax;
}
});
}
private static boolean executeBooleanJavascript(final WebDriver input, final String javascript) {
return (Boolean) ((JavascriptExecutor) input).executeScript(javascript);
}
我正在编写一个通用的基于 selenium phantomjs 的蜘蛛来访问和抓取网页。
程序的输入包括需要抓取的模板(css选择器),输出应该根据模板产生数据。
如果我们尝试从网站抓取图片,有时我们可能会得到空图片(如果执行时的页面源不包含图片,就会出现这种情况),这可以通过 wait 解决
然而,当网页为图像提供占位符时,会出现更具挑战性的问题,这些占位符稍后会通过 ajax
请求被真实图像 URL 替换。
问题是,如何确保 selenium 只在页面中包含真正的 URL 图像后才抓取图像。我正在考虑检查图像的 src
属性是否有更改,只有在一次更改后我才应该开始解析页面源代码。但是,不确定如何实施?或者这是一个好主意吗?
编辑
<html>
<head>
<style>
img {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<div id='wrapper'>
<div class='wrapper-child'>
<img data-backup='./1clr.jpg' src='./1bw.jpg'>
</div>
<div class='wrapper-child'>
<img data-backup='./2clr.jpg' src='./2bw.jpg'>
</div>
<div class='wrapper-child'>
<img data-backup='./3clr.jpg' src='./3bw.jpg'>
</div>
</div>
<script src='./jquery.js'></script>
<script type='text/javascript'>
$(document).ready(function() {
// setTimeout(function() {
//replace image placeholders
$.get("ajax/test.html", function(data) {
}).always(function() {
$('img').each(function() {
$(this).attr('src', $(this).attr('data-backup'));
});
});
// }, 1000);
});
</script>
</body>
</html>
假设我有这个页面,在 jquery 更新后如何使用 selenium 抓取图像?
如果该站点正在使用 jQuery,您可以检查以下内容以确保所有 ajax 交互都已完成。
jQuery.active == 0
检查此线程是否有相关问题:wait for an ajax call to complete with Selenium 2 web driver
编辑
此代码适用于我们:
public static int TIME_OUT_SECONDS = 10;
public static int POLLING_MILLISECONDS = 100;
public static final String JS_JQUERY_DEFINED = "return typeof jQuery != 'undefined';";
public static final String JS_JQUERY_ACTIVE = "return jQuery.active != 0;";
public static final String JS_DOC_READY = "return document.readyState != 'complete';";
public static final String JS_BLOCK = "return typeof $ != 'undefined' && typeof $.blockSelenium != 'undefined' && $.blockSelenium==true;";
public static void waitForJQuery(final WebDriver driver) {
new FluentWait<WebDriver>(driver).withTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS).pollingEvery(POLLING_MILLISECONDS, TimeUnit.MILLISECONDS).until(new Function<WebDriver, Boolean>() {
@Override
public Boolean apply(final WebDriver input) {
boolean ajax = false;
boolean jQueryDefined = executeBooleanJavascript(input, JS_JQUERY_DEFINED);
if (jQueryDefined) {
ajax |= executeBooleanJavascript(input, JS_JQUERY_ACTIVE);
}
boolean ready = executeBooleanJavascript(input, JS_DOC_READY);
boolean block = executeBooleanJavascript(input, JS_BLOCK);
ajax |= ready;
ajax |= block;
// continue if all ajax request are processed
return !ajax;
}
});
}
private static boolean executeBooleanJavascript(final WebDriver input, final String javascript) {
return (Boolean) ((JavascriptExecutor) input).executeScript(javascript);
}