Besoin de vider ensemble de l'arborescence du DOM avec id d'élément de sélénium serveur
J'ai été en utilisant python sélénium pour le web automatisation des tests. La partie clé de l'automatisation est de trouver le bon élément pour un utilisateur-objet visible dans une page HTML. La suite de l'API fonctionne la plupart du temps, mais pas tout le temps.
find_element_by_xxx, xxx can be id, name, xpath, tag_name etc.
Lorsque la page HTML est trop compliqué, je voudrais de recherche de l'arborescence dom. Me demande si il est possible de demander le sélénium serveur pour sérialiser l'ensemble DOM (avec l'id de l'élément qui peut être utilisé pour réaliser une action par le biais de webdriver serveur). Côté Client (script python) ne peut faire son propre algorithme de recherche pour trouver le bon élément.
Noter que python le sélénium peut obtenir la totalité de la page html par
drv.page_source
Cependant, cette analyse ne donne pas l'élément interne id de sélénium du serveur de point de vue, n'est donc pas utile.
EDIT1:
Paraphrase pour le rendre plus clair (merci @alecxe): ce qui est nécessaire ici, c'est une représentation sérialisée de tous les éléments du DOM (avec leur DOM structure conservée) dans le selenium server, cette représentation sérialisée peuvent être envoyés pour le côté client (un python de sélénium application de test), ce qui peut faire sa propre recherche.
Merci @Louis pour les précisions sur l'élément identificateur. Oui, la sérialisation doit à la fois avoir les éléments du DOM et les identifiants des éléments. Le point est de faire de la recherche entièrement sur le côté client.
la recherche j'devez effectuer est trop complexe pour find_element_by... type d'API peut faire. Je n'ai pas le code. Pour vous donner une idée, c'est comme trouver le champ de texte qui est "proche" de l'étiquette de "Limite". Oui, il n'est pas suffisamment précise pour express avec un Xpath, sélecteur css etc.
oui, en théorie c'est faisable par une série de
find_element_by
mais il est extrêmement inefficace. Je suis vraiment intéressé de voir votre execute_script
exemple, s'il vous plaît partager le lien si possible.OriginalL'auteur packetie | 2014-08-18
Vous devez vous connecter pour publier un commentaire.
Essayer:
Qui devrait correspondre à tous les éléments dans le document.
Mise à JOUR (pour correspondre à la question raffinements):
L'utilisation de javascript et de retourner le DOM comme une chaîne de caractères:
On dirait que vous voulez faire cela, alors: stackoverflow.com/questions/10520294/...
David, j'ai utilisé l'expression Xpath dans le sélénium script d'automatisation. Cependant, le Xpath est le côté client (sélénium script) demande à l' (sélénium) serveur pour faire une recherche XPath. Je voudrais obtenir le sérialisé DOM structure envoyé sur le côté client et de laisser le client lui-même faire la recherche Xpath.
OriginalL'auteur David K. Hess
Le Problème
Ok, donc il peut y avoir des cas où vous avez besoin pour effectuer une transformation substantielle d'une page sur le client (Python) côté plutôt que sur le serveur (navigateur). Par exemple, si vous avez une sorte de machine système d'apprentissage déjà écrit en Python et il a besoin pour analyser l'ensemble de la page avant d'effectuer des actions sur eux, alors bien qu'il est possible de le faire avec un tas de
find_element
appels, cela devient très cher parce que chaque appel est un aller-retour entre le client et le serveur. Et la réécriture qu'il fonctionne dans le navigateur est peut-être trop cher.Pourquoi Sélénium Identificateurs l'habitude de " faire
Cependant, je ne vois pas un efficace façon à obtenir une sérialisation des DOM ensemble avec Sélénium propres identifiants. Le sélénium crée ces identificateurs sur une base comme-nécessaire, lorsque vous appelez
find_element
ou lorsque les nœuds DOM sont renvoyées à partir d'uneexecute_script
appel (ou passé à la fonction de rappel quiexecute_async_script
donne le script). Mais si vous appelezfind_element
pour obtenir des identifiants pour chaque élément, alors vous êtes de retour à la case départ. Je ne pouvais imaginer la décoration de la DOM dans le navigateur avec les informations requises, mais il n'y a pas d'API publique pour demander une sorte de pré-affectation deWebElement
id. Comme une question de fait, ces identifiants sont conçus pour être opaque, de sorte que même si une solution réussi en quelque sorte à obtenir les informations nécessaires, je serais inquiète de la croix-navigateur viabilité et le soutien continu.Une Solution
Il y a cependant un moyen d'obtenir un système d'adressage qui permettrait de travailler sur les deux côtés: XPath. L'idée est d'analyser le DOM de la sérialisation dans un arbre sur le côté client et ensuite obtenir l'expression XPath, les nœuds que vous êtes intéressé et l'utiliser pour obtenir le correspondant WebElement. Donc, si vous devez effectuer des dizaines de client-serveur allers-retours pour déterminer le seul élément que vous devez effectuer un clic, vous seriez en mesure de réduire cela à une requête initiale de la source de la page, plus un seul
find_element
appel avec le XPath vous avez besoin.Ici est super simple preuve de concept. Il récupère le principal champ de saisie de Google en première page.
Notes:
Le code ci-dessus n'utilise pas
driver.page_source
parce que le Sélénium de la documentation, il n'y a aucune garantie quant à la fraîcheur de quoi il en retourne. Il pourrait être de l'état actuel du DOM ou à l'état de la DOM lorsque la page est chargée pour la première fois.Cette solution souffre exactement les mêmes problèmes que
find_element
souffre de concernant du contenu dynamique. Si le DOM changements alors que l'analyse est en cours, alors vous travaillez sur un état de la représentation du DOM.Si vous devez générer des événements JavaScript lors de l'exécution de l'analyse, et ces événements de modifier le DOM, alors vous devrez aller chercher les DOM nouveau. (Ceci est similaire à la précédente, mais une solution qui utilise
find_element
appels pourrait éviter le problème dont je parle dans ce point par la commande de la séquence d'appels avec soin.)lxml
'arbre peut éventuellement différer structurellement de l'arbre du DOM de telle manière que l'expression XPath, obtenus à partir delxml
n'est pas l'adresse de l'élément correspondant dans le DOM. Celxml
processus est nettoyé sérialisé vue que le navigateur a du HTML est passé. Par conséquent, tant que le code est écrit pour éviter les problèmes que j'ai mentionnés au point 2 et 3, je ne vois pas cela comme un scénario le plus probable, mais il n'est pas impossible.Heureux de vous aider! Vous devriez aussi regarder l'autre réponse que j'ai fournie, puisque c'est la méthode que j'ai mentionné dans mes commentaires précédents et est une méthode qui permettrait de prendre soin de beaucoup de cas. Il peut ne pas être ce que vous avez besoin maintenant, mais c'est une bonne chose que de savoir, en général.
C'est une bonne idée. Merci encore.
OriginalL'auteur Louis
Voir mon autre réponse pour les questions relatives à toutes les tentatives d'obtenir le Sélénium identifiants.
Encore une fois, le problème est de réduire à un tas de
find_element
appels afin d'éviter les aller-retours sont associés.Une méthode différente de mes autres réponse est d'utiliser
execute_script
à effectuer la recherche sur le navigateur et puis le retour de tous les éléments nécessaires. Par exemple, ce code n'est besoin de trois allers-retours, mais peut être réduite à un seul aller-retour:Ceci renvoie à un élément, l'élément de la mère et de l'élément de contenu textuel sur la base de ce sélecteur CSS je souhaite passer. Dans le cas où la page a jQuery chargé, j'ai pu utiliser jQuery pour effectuer la recherche. Et la logique peut obtenir d'aussi compliqué que nécessaire.
Cette méthode prend en charge la grande majorité des cas, lorsque la réduction des aller-retours est souhaitable, mais il ne prend pas soin d'un scénario comme celui que j'ai donné en illustration dans mon autre réponse.
OriginalL'auteur Louis
Vous pouvez essayer d'utiliser la page de l'objet modèle. Que des sons plus proche de ce que vous cherchez dans ce cas. Vous risquez de ne pas tout changer, mais au moins pour cette partie, vous pourriez envisager.
http://selenium-python.readthedocs.org/en/latest/test-design.html?highlight=page%20object
Vous pouvez aussi parcourir tous les éléments de la page et enregistrer un à un moment, mais il devrait y avoir une bibliothèque qui peut le faire. Je sais pour .Net il y a htmlAgility. Je ne suis pas sûr python.
Mise à jour
J'ai trouvé ce...peut-être vous aider.
Html Agility Pack pour python
OriginalL'auteur mutt
En fait, vous pouvez le faire assez facilement. Écrire la sortie dans un flux comme
var w = window.open...
et puisdocument.write...
de manière récursive parcourir le document objet de retour JSON.Stringify retour de chaque objet. Je vous suggère de jeter dans
typeof
.Je vous suggère d'ajouter une sorte de filtrage pour supprimer les propriétés que vous ne voulez pas voir. Aussi, je doute irait comme les navigateurs de détecter et de s'échapper des boucles récursives.
J'ai trouvé cette question, à la recherche de quelque chose de similaire, mais je m'attendais à un objet DataTable (je suis en utilisant .Net) que j'ai pu lier dans une sorte de fenêtre de débogage, quelque chose de mieux que le chrome. Avant j'ai utilisé firebug pour ce faire, mais c'est sorta morts.
De sorte que vous pourrait également obtenir ces données, mais en temps réel à l'aide d'un débogueur.
OriginalL'auteur user1529413