Загрузка содержимого 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 5

1 ответ:

Как я могу определить, когда я достиг нижней части страницы?

JS не работает хорошо для этого, поэтому я использовал jQuery, чтобы определить это. Как только я достигну дна, это будет истиной:

$(document).height() == ($(window).height() + $(window).scrollTop();

Есть ли что-нибудь, что отличает их уникальность? Ваш пример flickr содержит изображения, для этого можно использовать url-адрес изображения, используя WebElement.getAttribute("src") для создания уникального идентификатора.