避免重复产品刮擦的建议

时间:2011-09-19 22:33:06

标签: php mysql web-crawler unique

我编写了一个非常基本的抓取工具,可以从网站上删除产品信息,然后将其放入数据库中。

除了一些网站似乎有一个用于页面多个部分的不同网址外,一切运作良好。例如,产品网址可能是:

http://www.example.com/product?id=52

然后,它可能有另一个URL用于不同的部分,例如评论等:

http://www.example.com/product?id=52&revpage=1

我的抓取工具将此视为不同的网址。我找到了一些网站,其中一个产品有数百个不同的网址。我已经添加了逻辑,以便在网址中的哈希值之后忽略任何内容以避免锚点,但我想知道是否有人有任何建议来避免这个问题?可能有一个简单的解决方案,我没有看到。

目前,它放慢了抓取/抓取过程的速度,其中一个网站可能只有100个产品,它会添加数千个网址。

我想忽略查询字符串,甚至是查询字符串的某些部分,但产品ID通常位于查询字符串中,因此我无法找到方法,而不为每个网站的URL结构编写例外

2 个答案:

答案 0 :(得分:1)

详细说明我的评论......

您可以包含以下代码

$producturl //is the url where you first found a product to scrape
$nexturl //is the next url you plan to crawl
if (strpos($nexturl, $producturl) === false) {
    crawl
}
loop back to the next url...

我猜你正在按顺序爬行...这意味着你找到一个页面并抓取该页面上的所有链接...然后你回到一个级别并重复...如果你没有按顺序爬行,您可以存储找到产品的所有页面,并使用它来检查您计划爬网的新页面是否以您已爬网的网址开头。如果是,则不要抓取新页面。

我希望这会有所帮助。祝你好运!

答案 1 :(得分:0)

您可以使用数据库并在ID或名称上设置唯一约束。因此,如果您的抓取工具再次尝试添加此数据,则会引发异常。 最简单的唯一约束是主键。

编辑url param解决方案:

如果从网址中获取正确的参数时遇到问题,可能会从facebook api中剪切可能会有所帮助。

protected function getCurrentUrl($noQuerys = false) {
  $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'
    ? 'https://'
    : 'http://';
  $currentUrl = $protocol . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  $parts = parse_url($currentUrl); // http://de.php.net/manual/en/function.parse-url.php

  // drop known fb params
  $query = '';
  if (!empty($parts['query'])) {
    $params = array();
    parse_str($parts['query'], $params);
    foreach(self::$DROP_QUERY_PARAMS as $key) { // self::$DROP_QUERY_PARAMS is a list of params you dont want to have in your url
      unset($params[$key]);
    }
    if (!empty($params)) {
      $query = '?' . http_build_query($params, null, '&');
    }
  }

  // use port if non default
  $port =
    isset($parts['port']) &&
    (($protocol === 'http://' && $parts['port'] !== 80) ||
     ($protocol === 'https://' && $parts['port'] !== 443))
    ? ':' . $parts['port'] : '';


  // rebuild
  if ($noQuerys) {
      // return URL without parameters aka querys
      return $protocol . $parts['host'] . $port . $parts['path'];
  } else {
      // return full URL
      return $protocol . $parts['host'] . $port . $parts['path'] . $query;
  }