Je veux obtenir tous les liens d'un document HTML. Ce n’est pas un problème, mais apparemment, il place tous les liens dans un ordre alphabétique avant de les stocker dans un tableau un par un. Je veux avoir les liens dans l'ordre original (pas en ordre alphabétique).
Alors, y a-t-il une possibilité d'obtenir le premier lien trouvé, de le stocker, puis le second, ...? J'ai déjà essayé d'utiliser HtmlAgilityPack et les méthodes Webbrowser-Control, mais les deux sont classés par ordre alphabétique. La commande originale est importante pour les besoins ultérieurs.
J'ai entendu dire que cela pourrait être possible avec Regex, mais j'ai trouvé suffisamment de réponses, où ils disent qu'il ne faut pas l'utiliser pour l'analyse HTML. Alors, comment puis-je le faire?
Voici le code de Webbrowser-Control, que j'ai essayé d'utiliser pour obtenir les liens et les stocker dans un tableau:
private void btnGet_Click(object sender, EventArgs e)
{
HtmlWindow mainFrame = webFl.Document.Window.Frames["mainFrame"];
HtmlElementCollection links = mainFrame.Document.Links;
foreach (HtmlElement link in links)
{
string linkText = link.OuterHtml;
if (linkText.Contains("puzzle"))
{
arr[i] = linkText;
i++;
}
}
}
Merci d'avance, Opak
Vous pouvez obtenir le bon ordre en parcourant l'arborescence DOM à l'aide de l' API HTML DOM . Le code suivant fait ceci. Remarque, j'utilise dynamic
pour accéder à l'API DOM. C'est parce que WebBrowser
de HtmlElement.FirstChild
/ HtmlElement.NextSibling
ne fonctionnent pas à cet effet, car ils renvoient null
pour les nœuds de texte DOM.
private void btnGet_Click(object sender, EventArgs e)
{
Action<object> walkTheDom = null;
var links = new List<object>();
// element.FirstChild / NextSibling don't work as they stop at DOM text nodes
walkTheDom = (element) =>
{
dynamic domElement = element;
if (domElement.tagName == "A")
links.Add(domElement);
for (dynamic child = domElement.firstChild; child != null; child = child.nextSibling)
{
if (child.nodeType == 1) // Element node?
walkTheDom(child);
}
};
walkTheDom(this.webBrowser.Document.Body.DomElement);
string html = links.Aggregate(String.Empty, (a, b) => a + ((dynamic)b).outerHtml + Environment.NewLine);
MessageBox.Show(html);
}
[MISE À JOUR] Si vous avez vraiment besoin d'obtenir une liste d'objets HtmlElement
pour les balises <A>
, au lieu d'éléments dynamic
natifs, vous GetElementById
utiliser un petit truc en utilisant GetElementById
:
private void btnGet_Click(object sender, EventArgs e)
{
// element.FirstChild / NextSibling don't work because they stop on DOM text nodes
var links = new List<HtmlElement>();
var document = this.webBrowser.Document;
dynamic domDocument = document.DomDocument;
Action<dynamic> walkTheDom = null;
walkTheDom = (domElement) =>
{
if (domElement.tagName == "A")
{
// get HtmlElement for the found <A> tag
string savedId = domElement.id;
string uniqueId = domDocument.uniqueID;
domElement.id = uniqueId;
links.Add(document.GetElementById(uniqueId));
if (savedId != null)
domElement.id = savedId;
else
domElement.removeAttribute("id");
}
for (var child = domElement.firstChild; child != null; child = child.nextSibling)
{
if (child.nodeType == 1) // is an Element node?
walkTheDom(child);
}
};
// walk the DOM for <A> tags
walkTheDom(domDocument.body);
// show the found tags
string combinedHtml = links.Aggregate(String.Empty, (html, element) => html + element.OuterHtml + Environment.NewLine);
MessageBox.Show(combinedHtml);
}