Html Agility Pack - lecture du div InnerText dans le tableau

c# html-agility-pack web-scraping

Question

Mon problème est que je ne peux pas obtenir div InnerText de la table. J'ai réussi à extraire différents types de données, mais je ne sais pas comment lire div from table.

Dans l'image suivante, j'ai mis en évidence div, et je dois obtenir InnerText, en l'occurrence, le numéro 3.

Cliquez ici pour la première photo

J'essaie d'accomplir ceci en utilisant le chemin suivant:

"//div[@class='kal']//table//tr[2]/td[1]/div[@class='cipars']"

Mais je reçois l'erreur suivante:

Cliquez ici pour l'image du message d'erreur

En supposant que le reste du code soit écrit correctement, est-ce que quelqu'un pourrait me diriger dans la bonne direction? J'ai essayé de comprendre celui-ci, mais je ne peux obtenir aucun résultat.

Réponse acceptée

Votre problème est donc que vous vous appuyez sur des positions au sein de votre XPath. Bien que cela puisse être correct dans certains cas, ce n'est pas ici, car vous vous attendez à ce que le premier td dans un tr donné ait un div avec la classe.

En regardant la source dans Chrome, cela montre que ce n'est pas toujours le cas. Vous pouvez le voir en comparant l'élément "1" du calendrier à "2" et "3". Vous remarquerez que l'élément "1" comporte un certain nombre d'éléments, contrairement aux autres.

Votre requête XPath d'origine ne renvoie pas d'élément, c'est pourquoi vous obtenez l'erreur. Si la requête XPath que vous donnez à HtmlAgilityPack n'aboutit pas à un élément DOM, elle renverra la valeur null.

Maintenant, parce que vous n'avez pas montré tout votre code, je ne sais pas comment ce code est exécuté. Cependant, je suppose que vous essayez de parcourir tous les éléments du calendrier. Quoi qu’il en soit, vous avez plusieurs façons de le faire, mais je vais vous montrer que, avec le sélecteur de descendant XPath, vous pouvez tout saisir en une fois:

//div[@class='kal']//table//descendant::div[@class='cipars']

Cela renverra tous les éléments du calendrier (c'est-à-dire 1 à 30).

Cependant, pour obtenir tous les éléments dans une ligne particulière, vous pouvez simplement coller ce tr dans la requête:

//div[@class='kal']//table//descendant::div[@class='cipars']

Cela renverrait 2 à 8 (la deuxième ligne d'éléments de calendrier).

Pour cibler un site spécifique, vous devrez faire une hypothèse sur le code source du site Web. Il semble que chaque div "cipars" ait un ancêtre de td avec un datums classe .... donc pour obtenir la valeur "3" de votre question:

//div[@class='kal']//table//descendant::div[@class='cipars']

Espérons que cela suffira à montrer au moins le problème.

modifier

Bien que vous ayez un problème XPath, vous avez également un autre problème.

Le site est créé très étrangement. Le calendrier est chargé d'une manière étrange. Lorsque je tape sur cette URL, le calendrier est créé par un script Javascript appelant un service Web XML (écrit en PHP) qui calcule ensuite le table complet à utiliser pour le calendrier.

Comme il s'agit de Javascript (code côté client), HtmlAgilityPack ne l'exécutera pas. Par conséquent, HtmlAgilityPack ne "voit" même pas le tableau. Par conséquent, les requêtes à ce sujet reviennent comme "non trouvé" (null).

Manières autour de ceci: 1) Utilisez un outil qui appellera les scripts. Par cela, je veux dire charger un navigateur. Selenium est un excellent outil à utiliser pour cela. Ce sera probablement la meilleure solution globale car cela signifie que tous les scripts utilisés par le site seront appelés. Vous pouvez toujours utiliser XPath avec ce dernier pour que vos requêtes ne changent pas.

La deuxième méthode consiste à envoyer une demande au même service Web que la page. Est d'obtenir essentiellement en arrière le même code HTML que la page devient, et l' utilisation que avec HtmlAgilityPack. Comment fait-on cela?

Eh bien, vous pouvez facilement poster des données sur un service Web en utilisant C #. Juste pour la facilité d'utilisation, j'ai volé le code de cette question SO . Avec cela, nous pouvons envoyer la même demande que la page et récupérer le même code HTML.

Donc, pour envoyer des données POST, nous générons une méthode comme celle-ci .....

//div[@class='kal']//table//descendant::div[@class='cipars']

Nous pouvons l'appeler comme suit:

//div[@class='kal']//table//descendant::div[@class='cipars']

Comment ai-je eu cela? Eh bien, le fichier php que nous appelons est le service Web de la page et les données POST également. La façon dont j'ai découvert les données envoyées au service est de déboguer le code Javascript (à l'aide de la console de développeur de Chrome), mais vous remarquerez peut-être que c'est à peu près la même chose qui se trouve dans l'URL. Cela semble être intentionnel.

Le responseBody qui est renvoyé est le code HTML physique de la seule table du calendrier.

Que faisons-nous avec cela maintenant? Nous chargeons cela dans HtmlAgilityPack, car il est capable d'accepter du HTML pur.

//div[@class='kal']//table//descendant::div[@class='cipars']

Maintenant, nous collons ce XPath original dans:

//div[@class='kal']//table//descendant::div[@class='cipars']

Maintenant, nous imprimons ce qui devrait être "3", espérons-le:

//div[@class='kal']//table//descendant::div[@class='cipars']

Ma sortie, en l’exécutant localement, est bien: 3 .

Cependant, bien que cela vous permette de surmonter le problème que vous rencontrez, je suppose que le reste du site est comme ça. Si tel est le cas, vous pourrez toujours contourner le problème en utilisant la technique ci-dessus, mais des outils tels que Selenium ont été créés pour cette raison même.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi