2010-08-30 5 views
11

Quels sont les avantages et les inconvénients des bibliothèques suivantes?html grattage et requêtes CSS

De ce qui précède, je l'ai utilisé QP et il n'a pas réussi à analyser HTML invalide, et simpleDomParser, qui fait un bon travail, mais il fuit un peu mémoire à cause du modèle d'objet. Mais vous pouvez garder cela sous contrôle en appelant $object->clear(); unset($object); lorsque vous n'avez plus besoin d'un objet.

Y a-t-il d'autres racleurs? Quelles sont vos expériences avec eux? Je vais en faire un wiki communautaire, afin que nous puissions construire une liste utile de bibliothèques qui peuvent être utiles lors du raclage.


j'ai fait des tests basés sur la réponse de Byron:

<? 
    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>"; 

et obtenu

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

Répondre

7

j'utiliser dom simple html exclusivement jusqu'à ce que quelques SO'ers lumineux m'a montré la alléluia lumière . Utilisez simplement les fonctions DOM intégrées. Ils sont écrits en C et font partie du noyau PHP. Ils sont plus rapides que toute autre solution tierce. Avec firebug, obtenir une requête XPath est muey simple. Ce simple changement a permis à mes racleurs à base de php de fonctionner plus vite, tout en économisant mon temps précieux. Mes racleurs prenaient ~ 60 mégaoctets pour gratter 10 sites de façon asynchrone avec une boucle. C'était même avec la simple correction de mémoire html dom que vous avez mentionnée.

Maintenant, mes processus PHP ne dépassent jamais 8 mégaoctets.

Hautement recommandé.

EDIT

D'accord, je l'ai fait quelques repères. Built in dom est au moins un ordre de grandeur plus rapide.

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"; 
+0

cela ne fonctionne pas pour un balisage non valide. Combien plus rapide est-ce comparé à dom simple? – Quamis

+2

Cela ** fonctionne ** pour un balisage non valide. Je n'ai pas de benchmarks mais c'est au moins un ordre de grandeur plus rapide. Sur les grandes pages, html dom simple prend 1-2 secondes. Le DOM construit le fait en un clin d'œil. J'ai écrit beaucoup de scrapers avec ceci et je n'utiliserais jamais le simple html dom pour n'importe quoi encore jamais. –

+0

@Quamis Notez le @ devant loadHtml(). Avec cela retiré, vous verrez une tonne d'avertissements de html invalide étant contraints dans l'arbre dom. Fonctionne pour les navigateurs, fonctionne pour PHP aussi;) –