【问题标题】:html scraping and css querieshtml抓取和css查询
【发布时间】:2010-08-30 19:21:36
【问题描述】:

以下库的优缺点是什么?

从上面我已经使用了 QP,但它无法解析无效的 HTML,而 simpleDomParser 做得很好,但是由于对象模型,它有点泄漏内存。但是当您不再需要某个对象时,您可以通过调用$object->clear(); unset($object); 来控制它。

还有更多的刮刀吗?你和他们有什么经验?我打算把它变成一个社区 wiki,我们可以建立一个有用的库列表,在抓取时很有用。


我根据拜伦的回答做了一些测试:

    <?
    include("lib/simplehtmldom/simple_html_dom.php");
    include("lib/phpQuery/phpQuery/phpQuery.php");


    echo "<pre>";

    $html = file_get_contents("http://stackoverflow.com/search?q=favorite+programmer+cartoon");
    $data['pq'] = $data['dom'] = $data['simple_dom'] = array();

    $timer_start = microtime(true);

    $dom = new DOMDocument();
    @$dom->loadHTML($html);
    $x = new DOMXPath($dom);

    foreach($x->query("//a") as $node)
    {
         $data['dom'][] = $node->getAttribute("href");
    }

    foreach($x->query("//img") as $node)
    {
         $data['dom'][] = $node->getAttribute("src");
    }

    foreach($x->query("//input") as $node)
    {
         $data['dom'][] = $node->getAttribute("name");
    }

    $dom_time =  microtime(true) - $timer_start;
    echo "dom: \t\t $dom_time . Got ".count($data['dom'])." items \n";






    $timer_start = microtime(true);
    $doc = phpQuery::newDocument($html);
    foreach( $doc->find("a") as $node)
    {
       $data['pq'][] = $node->href;
    }

    foreach( $doc->find("img") as $node)
    {
       $data['pq'][] = $node->src;
    }

    foreach( $doc->find("input") as $node)
    {
       $data['pq'][] = $node->name;
    }
    $time =  microtime(true) - $timer_start;
    echo "PQ: \t\t $time . Got ".count($data['pq'])." items \n";









    $timer_start = microtime(true);
    $simple_dom = new simple_html_dom();
    $simple_dom->load($html);
    foreach( $simple_dom->find("a") as $node)
    {
       $data['simple_dom'][] = $node->href;
    }

    foreach( $simple_dom->find("img") as $node)
    {
       $data['simple_dom'][] = $node->src;
    }

    foreach( $simple_dom->find("input") as $node)
    {
       $data['simple_dom'][] = $node->name;
    }
    $simple_dom_time =  microtime(true) - $timer_start;
    echo "simple_dom: \t $simple_dom_time . Got ".count($data['simple_dom'])." items \n";


    echo "</pre>";

得到了

dom:         0.00359296798706 . Got 115 items 
PQ:          0.010568857193 . Got 115 items 
simple_dom:  0.0770139694214 . Got 115 items 

【问题讨论】:

    标签: php html web-scraping


    【解决方案1】:

    我以前只使用简单的 html dom,直到一些聪明的 SO'ers 向我展示了光明的哈利路亚。

    只需使用内置的 DOM 函数即可。它们是用 C 语言编写的,是 PHP 核心的一部分。它们比任何 3rd 方解决方案都更快更有效。使用 firebug,获取 XPath 查询非常简单。这个简单的改变使我基于 php 的爬虫运行得更快,同时节省了我宝贵的时间。

    我的抓取工具过去使用 curl 异步抓取 10 个站点需要大约 60 兆字节。即使是您提到的简单的 html dom 内存修复也是如此。

    现在我的 php 进程永远不会超过 8 兆字节。

    强烈推荐。

    编辑

    好的,我做了一些基准测试。内置 dom 至少要快一个数量级。

    Built in php DOM: 0.007061
    Simple html  DOM: 0.117781
    
    <?
    include("../lib/simple_html_dom.php");
    
    $html = file_get_contents("http://stackoverflow.com/search?q=favorite+programmer+cartoon");
    $data['dom'] = $data['simple_dom'] = array();
    
    $timer_start = microtime(true);
    
    $dom = new DOMDocument();
    @$dom->loadHTML($html);
    $x = new DOMXPath($dom); 
    
    foreach($x->query("//a") as $node) 
    {
         $data['dom'][] = $node->getAttribute("href");
    }
    
    foreach($x->query("//img") as $node) 
    {
         $data['dom'][] = $node->getAttribute("src");
    }
    
    foreach($x->query("//input") as $node) 
    {
         $data['dom'][] = $node->getAttribute("name");
    }
    
    $dom_time =  microtime(true) - $timer_start;
    
    echo "built in php DOM : $dom_time\n";
    
    $timer_start = microtime(true);
    $simple_dom = new simple_html_dom();
    $simple_dom->load($html);
    foreach( $simple_dom->find("a") as $node)
    {
       $data['simple_dom'][] = $node->href;
    }
    
    foreach( $simple_dom->find("img") as $node)
    {
       $data['simple_dom'][] = $node->src;
    }
    
    foreach( $simple_dom->find("input") as $node)
    {
       $data['simple_dom'][] = $node->name;
    }
    $simple_dom_time =  microtime(true) - $timer_start;
    
    echo "simple html  DOM : $simple_dom_time\n";
    

    【讨论】:

    • 这不适用于无效标记。这比简单的 dom 快多少?
    • 确实适用于无效标记。我没有基准,但它至少要快一个数量级。在大页面上,简单的 html dom 需要 1-2 秒。内置的 DOM 眨眼间就完成了。我已经用这个写了很多爬虫,我再也不会用简单的 html dom 做任何事情了。
    • @Quamis 注意 loadHtml() 前面的 @。删除后,您将看到大量来自无效 html 的警告被强制进入 dom 树。适用于浏览器,也适用于 php ;)
    • 你是对的,它的速度更快,它加载无效的 html,现在重新测试它
    • 我将您的答案编辑为使用 timestamp(true) 而不是简单的 timestamp()。
    猜你喜欢
    • 2015-06-11
    • 1970-01-01
    • 2014-05-10
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    相关资源
    最近更新 更多