Загрузка содержимого AJAX при прокрутке с помощью Selenium Wedriver
Я использую Selenium WebDriver для получения содержимого сайта. (Примечание: у сайта нет API. Жаль, что это не так.) Сайт использует AJAX для динамической загрузки содержимого при прокрутке пользователем. Чтобы получить этот контент, я использовал Javascript для прокрутки вниз, а затем пытался получить доступ к контенту с помощью findElements().
Чтобы внести ясность в настройку, страница содержит несколько вложенных элементов, одним из которых является div с классом "GridItems" (без имени или идентификатора). Этот div содержит много дочерних элементов с класс" Item " (опять же, без имени или идентификатора, только класс). Я хочу получить каждый элемент с классом "Item" в div. При первой загрузке страницы доступно около 25 элементов (не обязательно видимых в текущем окне, но доступных в DOM), а при прокрутке вниз загружается больше.
Мои основные проблемы заключаются в следующем: Во-первых, я хочу прекратить прокрутку, когда я доберусь до дна. Однако я не могу понять, какое условие остановки использовать. Как я могу определить, когда я достиг дна страницы? Окно.scrollheight не будет работать, потому что это даст высоту существующего окна, а не то, что будет после того, как он закончит добавлять больше контента. Я подумал о том, чтобы проверить, является ли элемент внизу страницы видимым/кликабельным, но если это не так, это может быть просто потому, что он еще не загружен, а не потому, что он не был достигнут. Даже использование ожидания может не сработать, потому что если оно истекает, я не знаю, потому что оно не достигло дна, или просто потому, что оно занимает много времени, чтобы загружать.
Вторая проблема заключается в том, что когда я прокручиваю вниз, он загружает еще несколько элементов, но в конечном итоге прокрутка вниз загружает больше снизу и отбрасывает верхние элементы DOM. Это означает, что я не могу просто прокрутить вниз, а затем использовать findElements (), чтобы получить все элементы, потому что многие из первых элементов исчезнут. Я знаю, сколько пунктов ожидать, поэтому в настоящее время я делаю следующее:
int numitems = 135;
List<WebElement> newitems;
List<WebElement> allitems = new ArrayList<WebElement>(50);
do {
//scroll down the full length of the visible window three times
for(int i=0; i < 3; i++)
{
//scroll down
js.executeScript("window.scrollTo(0, document.body.offsetHeight)");
}
//check how many items are now available
//if it runs too fast, it may get to the next line before it finishes scrolling;
//make it wait until the desired div is visible
WebElement cont = (new WebDriverWait(driver, 100))
.until(ExpectedConditions.presenceOfElementLocated(By.className("GridItems")));
//get all Items in the div
newitems = cont.findElements(By.className("Item"));
//add all the items extracted after scrolling 3 times to the list
allitems.addAll(newitems);
//repeat until there are more items in the general list than are expected
//to be found. This is hacky; I wish there was a better stopping condition
}while(numitems > allitems.size());
То есть я прокручиваю страницу три раза, получаю все элементы, доступные после прокрутите и добавьте их в список. Я повторяю это до тех пор, пока в списке не окажется больше элементов, чем я ожидал найти.
Проблема с этим заключается в том, что, поскольку прокрутка добавляет разное количество элементов в DOM каждый раз, часто происходит перекрытие между тем, что добавляется в список allitems на каждой итерации. Элементы-это просто объекты с уникальными идентификаторами, не содержащие никакой информации о фактическом HTML, поэтому я не могу проверить, дублируются ли они. Я также могу потерять некоторые предметы, если прокрутка не перекрывается идеально. Кроме того, поскольку я прокрутил вниз, более ранние элементы в списке, которые упали сверху, теряют связь с DOM, а затем я получаю исключение StaleElementReferenceException, когда я пытаюсь их обработать.
Я могу обрабатывать каждый элемент по мере его получения, хотя это сделает код неуклюжим. Это также позволит мне проверить его фактическое содержание и найти дубликаты. Я не уверен, что это гарантирует, что я не пропущу ни одного.
Есть ли у кого-нибудь есть предложения, как лучше всего это сделать? Я упускаю что-то очень важное/очевидное здесь? Другие вопросы здесь на SO о загрузке содержимого AJAX касаются несколько других проблем. (например, у меня обычно нет проблем с тем, что контент не загружается и приходится его ждать, хотя я включил ожидание.) Кажется, что должен быть лучший способ сделать это - не так ли?
Извините за длинное сообщение; надеюсь, оно было ясным.Большое вам спасибо., bsg
Правка:
Я понимаю, что принятый ответ отвечает только на часть вопроса. В остальном я обнаружил, что прокрутка вниз по одному экрану за раз и получение всех новых элементов каждый раз означало, что я не терял ни одного. После каждого свитка я загружал все элементы и выполнял некоторую обработку, чтобы сохранить содержимое каждого из них. Это вводит много избыточности, которую я использовал хэш-набор, чтобы устранить. Я останавливаю прокрутку, когда я достигаю дна, как определено кодом в ответ принят. Надеюсь, это поможет.1 ответ:
Как я могу определить, когда я достиг нижней части страницы?
JS не работает хорошо для этого, поэтому я использовал jQuery, чтобы определить это. Как только я достигну дна, это будет истиной:
Есть ли что-нибудь, что отличает их уникальность? Ваш пример flickr содержит изображения, для этого можно использовать url-адрес изображения, используя
$(document).height() == ($(window).height() + $(window).scrollTop();
WebElement.getAttribute("src")
для создания уникального идентификатора.