Vous n'êtes pas identifié(e).
Sauf que si je ne m'abuse, les nouvelles valeurs n'affectent pas le dom original. En effet si j'explore le dom à nouveau, je me rends compte qu'il n'a pas changé et je retrouve les valeurs d'origine des h2.
Info: foreach est un itérateur en lecteur seule, il n'est pas possible de modifier la valeur de $h2. Pour rendre $h2 modifiable, il convient de définir la boucle ainsi: foreach ($html->find('h2') as &$h2)
Si la méthode avec xpath marche, touche à rien
Si vraiment, tu veux rendre le script moins gourmand la solution est de parcourir qu'une seule fois l'ensemble du code HTML (xPath parcourt l'ensemble de caractère à chaque fois) et de de faire les remplacements à la volée.
Pour ce faire, une solution est de parcourir le code HTML, détecter les zones à remplacer, copier ce qui ne change pas, insérer le nouveau contenu et ainsi de suite.
Au final, on se retrouve avec le code HTML original et un code HTML où les textes ont été remplacés.
🔴 Hors ligne
Info: foreach est un itérateur en lecteur seule, il n'est pas possible de modifier la valeur de $h2. Pour rendre $h2 modifiable, il convient de définir la boucle ainsi: foreach ($html->find('h2') as &$h2)
tu utilises vraiment simple html dom ? cela marche très bien avec foreach ($html->find('h2') as $h2){}
Le problème est la méthode appelée dans le foreach, pas le foreach lui même. $h2->plaintext() ne changera pas l'objet dom $html par contre avec $h2->innertext = 'hello world'; Le dom $html est bel et bien modifié, même dans un foreach.
Je ne vois pas ce que tu veux dire par un itérateur en lecture seule, pour moi c'est un itérateur point. En effet tu peux modifier toutes les valeurs d'un array en passant par un foreach. Du coup je ne comprends pas ce que tu as voulu dire.
Si vraiment, tu veux rendre le script moins gourmand la solution est de parcourir qu'une seule fois l'ensemble du code HTML (xPath parcourt l'ensemble de caractère à chaque fois) et de de faire les remplacements à la volée.
C'est exactement ce que je fais, je ne parcours qu'une seule fois chaque noeud de de l'objet simple_html_dom
Pour ce faire, une solution est de parcourir le code HTML, détecter les zones à remplacer, copier ce qui ne change pas, insérer le nouveau contenu et ainsi de suite.
Comment faire ça était effectivement le problème à résoudre
🔴 Hors ligne
moi sur le site de Bigorno avec un replace de SEO par Bigorno le script d'execute en :
1 fois en 0.798 sec sur un PHP5.
10 fois 6.088 sec sur un PHP5
1 fois en 0.698 sec sur un PHP7
10 fois en 6.011 sec sur un PHP7
sur la page WIKI (https://fr.wikipedia.org/wiki/Optimisation_pour_les_moteurs_de_recherche) avec un replace de SEO par Bigorno le script d'execute en :
1 fois en 0.114 sec sur un PHP5
10 fois en 0.964 sec sur un PHP5
1 fois en 0.104 sec sur un PHP7
10 fois en 1.015 sec sur un PHP7
ce qu'on peu voir donc la c'est que le script n'est pas forcement gourmand mais c'est plutôt la vitesse du serveur en face qui va jouer ...
Ma version de test :
for ($i = 1; $i <= $total_execute; $i++) {
$doc = new DOMDocument;
@$doc->loadHTMLFile('https://fr.wikipedia.org/wiki/Optimisation_pour_les_moteurs_de_recherche');
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//text()');
foreach ($nodes as $node) {
$node->nodeValue = str_replace("SEO", "Bigorno", $node->nodeValue);
}
$output[] = $doc->saveHTML();
}
echo "<br>Script execute en " . number_format((microtime(true)-$timestart), 3) . " sec";
Apres oui le script peu etre plus gourmand selon la fonction de SPIN utilisé , mais je sais pas le debit que tu demande
🔴 Hors ligne
moi sur le site de Bigorno avec un replace de SEO par Bigorno le script d'execute en :
1 fois en 0.798 sec sur un PHP5.
10 fois 6.088 sec sur un PHP51 fois en 0.698 sec sur un PHP7
10 fois en 6.011 sec sur un PHP7sur la page WIKI (https://fr.wikipedia.org/wiki/Optimisation_pour_les_moteurs_de_recherche) avec un replace de SEO par Bigorno le script d'execute en :
1 fois en 0.114 sec sur un PHP5
10 fois en 0.964 sec sur un PHP51 fois en 0.104 sec sur un PHP7
10 fois en 1.015 sec sur un PHP7ce qu'on peu voir donc la c'est que le script n'est pas forcement gourmand mais c'est plutôt la vitesse du serveur en face qui va jouer ...
Ma version de test :
<?php
$timestart=microtime(true);
$output = array();
$total_execute = 10;
for ($i = 1; $i <= $total_execute; $i++) {
$doc = new DOMDocument;
@$doc->loadHTMLFile('https://fr.wikipedia.org/wiki/Optimisation_pour_les_moteurs_de_recherche');
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//text()');
foreach ($nodes as $node) {
$node->nodeValue = str_replace("SEO", "Bigorno", $node->nodeValue);
}$output[] = $doc->saveHTML();
}echo "<br>Script execute en " . number_format((microtime(true)-$timestart), 3) . " sec";
Apres oui le script peu etre plus gourmand selon la fonction de SPIN utilisé , mais je sais pas le debit que tu demande
On s'est pas compris, je disais pas que ton script était gourmand, le mien aussi traverse le dom, et quoi qu'il arrive c'est une méthode gourmande, bien optimiser la méthode de parsing est essentiel.
Si cela t'intéresse relis les problématiques que j'ai posté plus haut tu constateras que ta fonction de replacement ne marchera pas dans le cas d'utilisation dont j'ai parlé.
Sincèrement, je ne connais pas bien la classe domNode mais d'après ce que je vois sur la doc $node->nodevalue va te donner le plain text de node en question, mais aussi celui de ces enfants. Donc si j'ai <p>Salut <strong>les dev</strong></p>, lorsque je vais agir le plaintext du node correspondant à la balise <p>, je vais agir sur "salut les dev" sauf que j'aurai perdu les <strong></strong>
= 'hello world' va agir
Le contenu textuel de ce noeud et de ces descendants.
🔴 Hors ligne
Sincèrement, je ne connais pas bien la classe domNode mais d'après ce que je vois sur la doc $node->nodevalue va te donner le plain text de node en question, mais aussi celui de ces enfants. Donc si j'ai <p>Salut <strong>les dev</strong></p>, lorsque je vais agir le plaintext du node correspondant à la balise <p>, je vais agir sur "salut les dev" sauf que j'aurai perdu les <strong></strong>
Le contenu textuel de ce noeud et de ces descendants.
Non la preuve :
Fichier source : http://www.woozy.fr/source.html
url du test : http://www.woozy.fr/test.php
Code :
$output = $doc->saveHTML();
Dernière modification par ciboulette (2016-02-17 15:45:53)
🔴 Hors ligne
Je ne vois pas ce que tu veux dire par un itérateur en lecture seule, pour moi c'est un itérateur point. En effet tu peux modifier toutes les valeurs d'un array en passant par un foreach. Du coup je ne comprends pas ce que tu as voulu dire.
//itinéation en lecteur/écriture
$N = array(1, 2, 3);
$i = 0;
foreach ($N as &$n) {
$n = $i;
}
print_r($N);
?>
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 0
[1] => 0
[2] => 0
)
Dans ton cas, foreach remplace les valeurs car les variables ne sont pas les mêmes dans l'array à parcourir et la valeur à fixer.
C'est exactement ce que je fais, je ne parcours qu'une seule fois chaque noeud de de l'objet simple_html_dom
A vérifier, $html->find('*') parcourt à chaque fois l'ensemble du code HTML pour trouver les nodes.
Mets voir un compteur dans ta boucle pour trouver le nombre de fois où $html->find('*') est lancé.
tu utilises vraiment simple html dom ?
Comment faire ça était effectivement le problème à résoudre
J'utilise très rarement simple html dom et cie car bien souvent le code HTML des sites web est crade ou l'encode est foireux. Et donc le parseur HTML part en sucette.
La méthode en une passe utilise strpos pour trouver le début et la fin des tags HTML puis substr pour copier le code qui ne change pas. Pas sûr que cela apporte beaucoup dans le cas de spin hormis un défi de geek pour qques mses
🔴 Hors ligne
Bigorno a écrit :Sincèrement, je ne connais pas bien la classe domNode mais d'après ce que je vois sur la doc $node->nodevalue va te donner le plain text de node en question, mais aussi celui de ces enfants. Donc si j'ai <p>Salut <strong>les dev</strong></p>, lorsque je vais agir le plaintext du node correspondant à la balise <p>, je vais agir sur "salut les dev" sauf que j'aurai perdu les <strong></strong>
Le contenu textuel de ce noeud et de ces descendants.
Non la preuve :
Fichier source : http://www.woozy.fr/source.html
url du test : http://www.woozy.fr/test.php
Code :
$doc = new DOMDocument;
@$doc->loadHTMLFile('http://www.woozy.fr/source.html');
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//text()');
foreach ($nodes as $node) {
$node->nodeValue = str_replace("dev", "Bigorno", $node->nodeValue);
$node->nodeValue = str_replace("Salut", "Coucou", $node->nodeValue);
}$output = $doc->saveHTML();
Merci Ciboulette de m'avoir contacté sur skype
J'ai vérifier le test qui l'a mis en place et cela fonctionne parfaitement, sur deux remplacements, c'est très rapide, je vais tester grandeur nature pour me faire une idée définitive, mais tout porte à croire que c'est largement mieux que la méthode que j'ai utilisé. Je vous tiens au courant.
🔴 Hors ligne
Hello, moi je fais encore du simple html dom, mais ciboulette ma montré comment il faisait avec dom document et xpath et ça marche très bien, même beaucoup plus rapide.
comme j'ai réussi à faire ce que je voulais, je me suis arrêté à simple html dom, mais pour faire les choses bien, je devrai utiliser la méthode proposée par ciboulette
Dernière modification par Walid (2016-10-19 13:20:29)
🔴 Hors ligne