首页 > 解决方案 > 计算最后一个工作页面以进行抓取的最快方法

问题描述

我正在尝试抓取一个网站,我不想被迫递归地抓取每个页面,直到“结束”。

我希望能够只获取最后一页,或介于两者之间的任何页面。

大多数时候这不是问题,但这个网页是不同的。例如:

我在“Logitech”上进行搜索查询

该网站返回我要使用的以下信息:

但是,找到的产品总数似乎是虚假信息,分页也是如此,因为当我尝试访问https://website.com/products?q=Logitech&page=500时没有产品。这也适用于较低的值,例如:499、498、450、400、350 等。

因此,我尝试在脑海中“计算”可能的页码,然后得出实际的最后页码:166

我通过检查是否有结果来“计算”这个:

所以我制作了一个测试脚本来复制我查找页码的方法(repl.it 链接): https ://repl.it/@SaltyPotato1/LastPageCalculator

但我对他的剧本有两个问题(我希望你们能帮助我):

  1. 这个脚本“知道”正确的值(166),所以当我抓取时它可以使用>和运算符;<在这种情况下它只能检查是否有结果:产品。这意味着只有 2 个选项:

    • 如果有结果,则意味着:页码太低 实际上是最后一个页码。
    • 如果没有结果则意味着:页码太高
  2. 我觉得脚本/计算可以改进,因为有些值被发出了两次。

我该怎么做才能确定它是否实际上是最后一页而不是实际最后一页“下方”的页码。我怎样才能最小化计算这个请求的数量。

我期待您的回答/帮助!

标签: javascriptalgorithmweb-scrapingpagination

解决方案


一般来说,您不应该知道所有类型产品的所有页码。您需要的是使用二进制搜索算法找到正确的最大页数。为此我建议使用HTTP Head请求来检查该路由是否存在,如果服务器不支持该方法,您可以尝试获取请求并仅检查响应的http状态码,这样您就不需要进行复杂的计算/ dom 查询只是为了找出正确的最大页数。

您的代码会有轻微的变化。

function findMaxPageCount(totalProductCount = 1000, productPerPage = 1){
  const lo = 1;
  const hi = totalProductCount/productPage;
  let mid;
  let actualMaxPage = -1;
  while(lo <= hi){
    mid = Math.floor((lo + hi)/2.0);

    if(pageExists(mid)){
      actualMaxPage = mid;
      lo = mid + 1;
    }else{
      hi = mid - 1;
    }
  }

  return actualMaxPage;
}

上述方法,不会再次搜索同一页面,因此阅读次数最少,最多Math.ceil(log2(totalProductCount/productPage))


推荐阅读