Voglio ottenere tutti i link di un documento HTML. Questo non è un problema, ma a quanto pare mette tutti i link in ordine alfabetico prima di memorizzarli in un array uno per uno. Voglio avere i collegamenti nell'ordine originale (non in ordine alfabetico).
Quindi c'è qualche possibilità di ottenere il primo link trovato, memorizzarlo, poi il secondo, ...? Ho già provato a utilizzare HtmlAgilityPack e i metodi di controllo Webbrowser, ma entrambi li ordiniamo alfabeticamente. L'ordine originale è importante per scopi successivi.
Ho sentito che potrebbe essere possibile con Regex, ma ho trovato abbastanza risposte, in cui dicono che non dovresti usarlo per l'analisi HTML. Quindi, come posso farlo?
Ecco il codice Webbrowser-Control, ho provato a utilizzare per ottenere i collegamenti e memorizzarli in un array:
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++;
}
}
}
Grazie in anticipo, Opak
Puoi ottenere l'ordine corretto camminando sull'albero DOM utilizzando l' API DOM HTML . Il seguente codice fa questo. Nota, utilizzo dynamic
per accedere alle API DOM. Questo perché WebBrowser
s' HtmlElement.FirstChild
/ HtmlElement.NextSibling
non funzionano per questo scopo, che tornano null
per Dom nodi di testo.
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);
}
[AGGIORNAMENTO] Se hai davvero bisogno di ottenere un elenco di oggetti HtmlElement
per i tag <A>
, invece di elementi nativi dynamic
, è ancora possibile con un piccolo trucco usando 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);
}