0
votes

XPath: Comment obtenir du texte entre 2 balises HTML avec le même niveau?

Je suis nouveau à et i 'M Utilisation de pour obtenir du texte de différents HTML pages générées.
Je reçois le {id} d'une balise d'en-tête de l'utilisateur (

texte ) . J'ai besoin d'obtenir du texte de toutes les balises HTML entre cet en-tête et l'en-tête suivant du même niveau. Donc, si l'en-tête est H1, j'ai besoin d'obtenir tout texte de toutes les balises jusqu'à la prochaine en-tête H1.
Tous les identifiants d'en-têtes ont le même modèle "titre- {id}" où {id} est généré.
Pour que cela soit plus clair ici, voici un exemple: XXX

NOTE: Je ne sais pas quel est-ce que cela pourrait être. Il pourrait s'agir de l'une des balises HTML en-tête de

à


Tout en essayant que peu de choses autour, j'ai remarqué que je ne suis pas sûr que le prochain en-tête ait le même niveau ou même existe. Puisque les en-têtes sont utilisés comme titres et sous-titres. L'identifiant donné peut être de dernier sous-titre, je vais donc avoir un en-tête de niveau supérieur après ou même être le dernier de la page. Donc, basicaly, je n'ai que l'identifiant de l'en-tête et je dois obtenir tout texte du "paragraphe".


Travailler autour de:

J'ai trouvé une solution de solution de contournement:

Je le fais en 3 étapes:
Tout d'abord, j'utilise // * [@ id = 'title- {id}] qui me permet d'obtenir la ligne complète avec la balise alors je sais maintenant quelle étiquette il est.
Deuxièmement, j'utilise // * [id = 'title- {id}] / suivant-frère :: * Cela permet de rechercher l'en-tête suivant du même niveau ou supérieur {myheader}.
Enfin, j'utilise // * [id = 'title- {id}] / suivant-frère :: * et // {myheader} //-frère précédent :: * << / Code> Pour obtenir ce qui est entre deux entre ou allez 'jusqu'à la fin de la page si aucun en-tête trouvé.


0 commentaires

3 Réponses :


2
votes

Voici le XPath pour obtenir tous les éléments entre les balises H2.

<html><head></head><body>
 
        ...
        <h2 id="tittle-id1">id1</h2>
		  <h3 id="tittle-id3"> h3 tag</h3>
		  <h4 id="tittle-id4"> h4 tag</h4>
		  <h3 id="tittle-id5"> 2nd h3  tag</h3>
        bunch of tags containing text I want to get
		   <h5 id="tittle-id6"> h5 tag </h5>
        <h2 id="tittle-id2">id2</h2>
		<h4 id="tittle-id7"> 2nd h4 tag</h4>
        ...
    
	
</body></html>


14 commentaires

Cela fonctionnerait si je savais ce que serait la balise HTML en-tête (

dans l'exemple). Mais si vous lisez attentivement, je n'ai que l'identifiant. Je ne sais pas ce que l'en-tête tag est. Il pourrait être n'importe lequel des «EM à partir de

à


Vous avez, laissez-moi mettre à jour ma réponse qui obtiendra tout élément entre deux balises basées sur l'ID.


Votre solution semble impliquer que je sais que n que je ne le fais pas. Mais je pense que c'est ma faute de ne pas être plus précise. Lorsque j'ai dit ID1 ou ID2, il n'était qu'un exemple l'identifiant réel est une chaîne générée du titre réel.


n IN, il n'y a pas le numéro de ID . C'est le nième article, vous devez utiliser une boucle pour obtenir toutes les informations en-têtes et dans le cadre de la boucle, vous pouvez mettre à jour la valeur n .


Ouais c'est ce que j'ai fait. Vérifiez ma dernière mise à jour que vous trouverez peut-être le nouveau travail autour d'une bonne solution. Dans quel cas je posterai comme solution et vérifiez-le aux autres à utiliser.


@supputuri ne devrait pas être le premier xpath être // h2 / frère suivant :: * [Compte (suivant (frère suivant :: h2) <2] afin que vous incluiez les frères et sœurs suivants du dernier < Code> H2 ?


@ Cj7 op ne connaît pas la balise h? pour que vous ne puissiez pas le code dur que dans le XPath.


@Deyesta Pouvez-vous s'il vous plaît vérifier avec ce xpath // * [@ Id = 'Tittle-ID1'] / Suivant :: * [Nombre (SIBLAGE suivant :: * [Nom () = Nom (précédé Sibling :: * [@ @ @ Id = 'Tittle-Id1'])]) = 1] et laissez-moi savoir. Afin que je puisse mettre à jour cela dans la réponse. Cela apportera tous les éléments entre deux balises H? basées sur le premier h? ID TAG fournie par l'utilisateur.


@SUPPUTURI OK, mais ma différence fait <2 au lieu de = 1


@ Cj7 s'il est <2 , il trouvera tout l'élément suivant après la prochaine balise H2. Vérifiez votre XPath avec le HTML que j'ai ajouté dans la réponse. Selon l'OP, tous ces h? sont des frères et sœurs qui sont là où la complexité et nous ne sommes pas sûrs de l'ordre des balises.


@SUPPUTURI Votre XPATH m'a donné un paragraphe attendu le seul problème est qu'il n'en a donné qu'un autre n'est pas celui étiqueté par l'ID que j'ai donné


Pouvez-vous me ping la xpath que vous avez utilisé?


J'ai utilisé ce xpath: // * [@ Id = 'Tittle-ID1'] / Suivant :: * [Nombre (SIBLAGE suivant :: * [Nom () = Nom (précisé-lafrage :: * [@ ID = 'Tittle-ID1'])])]) = 1] . On dirait que ce XPath donne exactement un "paragraphe" sauf que c'est pour ID de titre? . Je ne suis pas en liberté de partager un exemple de vie réel et c'est la raison pour laquelle vous ne pouvez pas obtenir la bonne réponse.


J'ai essayé votre xPath et sur la page d'échantillonnage que j'ai téléchargée dans la réponse et que cela fonctionne comme prévu. Est-il possible de se moquer des données et de partager la structure exacte?



1
votes

Par exemple, car les prédicats dans XPath Filter la liste de nœuds de contexte Vous ne pouvez pas effectuer une sélection de jointure, sauf si vous ne pouvez réintroduire des valeurs cibles d'un contexte relatif de vos valeurs source. Exemple Sélection de tous les éléments avec le même nom que d'avoir un attribut ID spécifique: xxx

maintenant, pour le "em>" entre les marques " Utilisez comme généralement la méthode kaysienne d'intersection: xxx

test dans http://www.xpathtester.com/xpath/0dcfdf59DCCB8FAF3705C22167AE45F1


3 commentaires

Lorsque je teste votre code par rapport à vos données réelles sur votre plate-forme de test, j'obtiens l'erreur suivante: Erreur - semble que XML n'est pas bien formé: le nom de l'entité doit immédiatement suivre "&" dans la référence d'entité.


Je l'ai essayé avec Scrapy, je reçois tout le texte de l'ID à la fin du document peut-être qu'il est dû au même fait mal formé XML


@Deyesta Cela fonctionne et il y a le cas de test avec votre propre échantillon d'entrée. S'il n'y a pas d'autre entrée pour que cette expression XPath ne sélectionne pas ce que vous voulez, veuillez être libre de poster votre cas de test comme je l'ai fait.



0
votes

C'est ce qui a fonctionné pour moi: strong>

Pour cela, gardez à l'esprit que j'utilise avec :

name_query = u"//*[name()=name(//*[@id='"+id+"'])]"
all = response.xpath(name_query)
for selector in all.getall():
     if self.id in selector:
          position = all.getall().index(selector)
balise = "h" + all.getall()[position].split("<h")[1][0]
title = all.getall()[position].split(">")[1].split("<")[0]
query = u"//*[preceding-sibling::"+balise+"[1] ='"+title+"' and following-sibling::"+balise+"]"
self.log('query = '+query)
results = response.xpath(query)
results.pop(len(results)-1)
with open(filename,'wb') as f:
    for text in results.css("::text").getall():
        f.write(text.encode('utf-8')+"\n")


0 commentaires