【问题标题】:Scraping an infinite scroll page stops without scrolling抓取无限滚动页面停止而不滚动
【发布时间】:2015-03-13 22:59:37
【问题描述】:

我目前正在使用 PhantomJS 和 CasperJS 来抓取网站中的链接。该站点使用 javascript 来动态加载结果。然而,下面的 sn-p 并没有让我得到页面包含的所有结果。我需要向下滚动到页面底部,查看微调器是否出现(意味着还有更多内容要来),等到新内容加载完毕,然后继续滚动直到不再显示新内容。然后将类名.title 的链接存储在一个数组中。链接到webpage 进行抓取。

var casper = require('casper').create();
var urls = [];
function tryAndScroll(casper) {
  casper.waitFor(function() {
    this.page.scrollPosition = { top: this.page.scrollPosition["top"] + 4000, left: 0 };
    return true;
  }, function() {
    var info = this.getElementInfo('.badge-post-grid-load-more');
    if (info["visible"] == true) {
      this.waitWhileVisible('.badge-post-grid-load-more', function () {
        this.emit('results.loaded');
      }, function () {
        this.echo('next results not loaded');
      }, 5000);
    }
  }, function() {
    this.echo("Scrolling failed. Sorry.").exit();
  }, 500);
}

casper.on('results.loaded', function () {
  tryAndScroll(this);
});

casper.start('http://example.com/', function() {
    this.waitUntilVisible('.title', function() {
        tryAndScroll(this);
      });
});

casper.then(function() {
  casper.each(this.getElementsInfo('.title'), function(casper, element, j) {
    var url = element["attributes"]["href"];
    urls.push(url);
  });
});

casper.run(function() {
    this.echo(urls.length + ' links found:');
    this.echo(urls.join('\n')).exit();
});

【问题讨论】:

    标签: javascript phantomjs casperjs


    【解决方案1】:

    我查看了该页面。您的误解可能是您认为 .badge-post-grid-load-more 元素会在下一个元素加载后立即消失。不是这种情况。它根本没有改变。您必须找到另一种方法来测试是否将新元素放入 DOM。

    例如,您可以检索当前的元素数量并使用waitFor 来检测数量何时发生变化。

    function getNumberOfItems(casper) {
        return casper.getElementsInfo(".listview .badge-grid-item").length;
    }
    
    function tryAndScroll(casper) {
      casper.page.scrollPosition = { top: casper.page.scrollPosition["top"] + 4000, left: 0 };
      var info = casper.getElementInfo('.badge-post-grid-load-more');
      if (info.visible) {
        var curItems = getNumberOfItems(casper);
        casper.waitFor(function check(){
          return curItems != getNumberOfItems(casper);
        }, function then(){
          tryAndScroll(this);
        }, function onTimeout(){
          this.echo("Timout reached");
        }, 20000);
      } else {
        casper.echo("no more items");
      }
    }
    

    我还稍微简化了tryAndScroll。有完全不必要的函数:第一个 casper.waitFor 根本没有等待,因此永远无法调用 onTimeout 回调。

    【讨论】:

    • +1 太好了,您对我的误解是正确的。现在当我运行时出现错误:Wait timeout of 10000ms expired, exiting.。你能发布整个代码块吗?我一定是把它放在一起错了
    • 是的,问题是如果不传递 onTimeout 回调,就会抛出超时错误,并且脚本会过早停止。我添加了回调并增加了超时。请记住,现在页面上有 600 个链接和一个新创建的链接来打开第二个页面,可以滚动以加载更多项目。
    • 完美!我现在了解 onTimeout 回调的问题
    • 你说得对,它会刮掉所有 600 个结果,是否有可能只刮掉最多 100 个结果?
    • 当然,curItems 变量就在那里。您可以使用另一个 if 块来检查它是否大于 100,并且只有在小于 100 时才执行casper.waitFor
    猜你喜欢
    • 2023-03-08
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 2012-09-13
    相关资源
    最近更新 更多