【问题标题】:Effiecint way to crawl a website爬取网站的有效方法
【发布时间】:2013-12-04 17:03:36
【问题描述】:

假设有一个分类网站,每个产品的唯一 URL 只是一个数字,例如: example.com/product/12345/ 现在,让我们假设每个数字都给页面中的不同产品一个结果,并说我想扫描所有 URL 并通过从 ex 中提取信息来从页面中获取每个信息:<div id='info'>someinfo</div> 现在我试图用类似的东西来做到这一点

$URL = 1000; 

for($i=1; $i < $URL; $i++){
  $content = file_get_contents("http://example.com/products/$i"); 
  $info = //get the exact info from div and 
  file_put_contents('file.txt', $info); 
}

即使此脚本以某种方式工作,它也未能写入前 5 个以上的结果,然后由于内存限制导致我的系统崩溃。所以,我想知道这是怎么做到的。

我可以使用 DOM 对象来获取 div 的内容,但真正的问题是如何不让脚本冻结页面。

有什么解决办法吗?

【问题讨论】:

  • 您可以尝试使用 cURL 库。在我看来,它必须比使用 file_get_contents 更有效
  • 您应该考虑对单个请求需要多长时间进行基准测试。执行 1000 个请求并将它们一次全部写入文件可能会使您的脚本超时。
  • 您确定遇到内存问题而不是脚本超时?我没有看到任何会引入内存泄漏的东西,所以只要你有足够的内存分配来保存$content,你用来派生$info$info 本身的DOM 对象,我认为内存会不是约束。再说一遍,也许您在代码示例中遗漏了一些可能有问题的内容。
  • @MikeBrant 这不是内存。对不起,这是脚本超时。我总是混淆这两者。所以,我想我应该去 forcURL 吗?正如 falconspy 所建议的那样?
  • @ANW 我认为您没有内存问题。您正在覆盖变量,因此没有任何变量坐在那里等待垃圾收集。 set_time_limit(0) 将允许脚本在完成之前运行。

标签: php web-crawler


【解决方案1】:

我建议为此类爬虫创建 shell 脚本。那你就不用关心超时了:

#!/usr/bin/env php
<?php
$url = 1000;
for ($i = 1; $i < $url; ++$i) {
    $content = getContent("http://example.com/products/$i");
    $info = getInfo($content);
    file_put_contents('file.txt', implode("\n", $info), FILE_APPEND);
}

function getContent($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    $curl_errno === 0 or die("cURL Error ($curl_errno): $curl_error\n");
    //sleep(2); // Pause 2 sec to avoid ban :)
    return $data;
}

function getInfo($content) {
    $doc = new DOMDocument();
    $doc->loadHTML($content);
    $xpath = new DOMXPath($doc);
    $result = array();
    // Adopt this block for your needs. This is just example 
    $elements = $xpath->query("//*[@id='info']");
    foreach ($elements as $element) {
        $result[] = $element->nodeValue;
    }
    return $result;
}

【讨论】:

    【解决方案2】:

    我无法对此进行测试,因为我使用的在线代码编辑器不允许我给它$_GET 值,但我想这是诱使 PHP 立即运行代码的最简单方法限制。 (或类似的东西)

    $url = intval($_GET['url']);
    if ($url >= 1) {
        $content = file_get_contents("http://example.com/products/$url"); 
        $info = //get the exact info from div and 
        file_put_contents('file.txt', $info);
        ob_end_flush();
        $url--;
        header("Location: ./thisfile.php?url=$url");
    }
    

    【讨论】:

    • 你不是说while吗?
    • @raam86 有这样的东西,其中 php 将运行很长时间,我更喜欢将每个不同的操作移动到页面加载中。随着流程的继续,这甚至可以提供反馈。 header 调用将导致循环
    猜你喜欢
    • 1970-01-01
    • 2012-09-24
    • 2019-07-19
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    相关资源
    最近更新 更多