Avatar billede bomann Nybegynder
05. september 2006 - 16:07 Der er 6 kommentarer og
1 løsning

Parse HTML uden brug af WebBrowser

Oprindeligt havde jeg lavet en HTML parser ved at benytte document.links og document.images i webbrowser komponenten - men da denne anvender multible threads kunne det ikke forenes med min aspx side. Hertil kommer at webbrowser komponenten var forholdsvis tung i forhold til det job den skulle udføre.

Derfor vil jeg gå en anden vej, og grabbe html'en med WebResponse.

Jeg er kommet så langt, at jeg har alt html'en i en streng, og nu kommer så mit spørgsmål:

Hvordan får jeg html'en ind i en instans af document eller what ever, så jeg får samme nemme tilgang til links, images og andre tags som webbrowser.document tilbyder?

Det skal selvfølgelig kunne anvendes i en class library fra aspx.
Avatar billede nielle Nybegynder
05. september 2006 - 19:08 #1
Imiddelbart ser det ikke ud til at man selv kan oprette et objekt af HtmlDocument-klassen. Den har i hvert fald ingen constructor, men dette er selvfølgeligt ingen garanti.

Selv ville jeg bruge regulære udtryk til at parse HTML-koden, men det er selvfølgeligt ikke helt så ligetil som hvis man kunne få et HtmlDocument-objekt til at klare opgaven for sig.
Avatar billede bomann Nybegynder
06. september 2006 - 09:09 #2
Kan mshtml.HTMLDocument mon gøre noget for mig?
Avatar billede nielle Nybegynder
06. september 2006 - 21:40 #3
Det tog sin tid at finde den, men måske er dette her løsningen for dig:

Start med at oprette en reference til Microsoft.mshtml

- og prøv så med følgende kode:


using System;
using System.Threading;
using mshtml;

namespace e730507
{
    class Program
    {
        static void Main(string[] args)
        {
            HTMLDocument oHTML = new HTMLDocument();

            oHTML.write(null);  // Disse to linjer er vigtige...
            oHTML.close();  // ...ellers får man en exception

            IHTMLDocument2 oIHTML = oHTML.createDocumentFromUrl("http://www.eksperten.dk/spm/730507", "");

            while (oHTML.readyState != "complete")
            {
                Thread.Sleep(50);
            }
            while (oIHTML.readyState != "complete")
            {
                Thread.Sleep(50);
            }

            Console.WriteLine(oIHTML.title);

            foreach (IHTMLElement link in oIHTML.links)
            {
                Console.WriteLine(link.outerHTML);
            }

            foreach (IHTMLElement image in oIHTML.images)
            {
                Console.WriteLine(image.outerHTML);
            }
        }
    }
}
Avatar billede bomann Nybegynder
07. september 2006 - 08:23 #4
Det er fantastisk - 1000 tak :)
Fortæl mig lige hvor og hvordan du finder frem til sådan et eksempel!?

NB: Husk at poste "Svar"
Avatar billede nielle Nybegynder
07. september 2006 - 08:59 #5
> Fortæl mig lige hvor og hvordan du finder frem til sådan et eksempel!?

Uha, det er jo en lang og snørklet vej som jeg ikke selv helt kan huske mere ;^)

Det startede dog med at du spurgte 06/09-2006 09:09:50. Jeg spekulerede på om det var muligt, men siden at jeg aldrig selv har arbejdet med mshtml.HTMLDocument startede jeg med at går på Google:

http://www.google.dk/search?hl=da&q=mshtml.HTMLDocument&btnG=Google-s%C3%B8gning&meta=

Det allerførste hit har den lovende titel:

"CodeGuru: Parsing HTML without Using the Browser Control"

Koden var godt nok på VB6 (ikke en gang VB.Net), men så svært er det nu heller ikke at oversætte den til C#.

Uheldigvis ville det ikke kompilere uden videre, så jeg kiggede lidt i de andre hits fra søgningen. F.eks. dette:

http://www.codecomments.com/archive293-2005-2-406644.html

Hvis du kigger efter vil du se at meget af kodestrukturen fra Tony Proctor’s indlæg, 2005-02-24, 3:55 pm, har overlevet i min endelige kode. :^)

Godt nok ville det nu kompilere, men det gav til gengæld en runtime-fejl som ikke var særlig hjælpsom.

Ud at søge igen. Jeg kan ikke lige huske hvilke søgekriterier jeg brugte (kun at der kom en C# med i søgestrengen ... måske var det noget ved oversættelsen VB -> C# som jeg havde misset). Jeg havnede i hvert fald på denne side:

http://www.dotnet247.com/247reference/msgs/1/6968.aspx

Han havde også nogle problemer med at få sin kode til at virke, men det lykkedes og i den endelige kode har han disse par linjer:

"
// This is the key ingredient - have to put some HTML
// in the DOM before using it, even though we're not
// accessing the DOM.
iDoc2a.write("<html></html>");
iDoc2a.close();
"

Det varede lidt tid, men på et eller andet tidspunkt var der noget som begyndte at gnave: I de kodeeksempler der kompilerede, men fejlede runtime, havde der ikke været sådan noget. Det var da et forsøg værd, og ja-sgu!, det virkede. Du må bare ikke spørge mig om hvorfor.

Resten var derefter rimeligt trivielt at stykke sammen.

Det var den pæne vej igennem, men undervejs kom jeg da ud af mange biveje. F.eks. fik jeg kigget på AxWebBrowser (men der havde nok været de samme problemer med denne som med WebBrowser), jeg fik kigget på .Net utility-programmer som AxImp og TlbImp.
Avatar billede nielle Nybegynder
07. september 2006 - 08:59 #6
... og et svar :^)
Avatar billede bomann Nybegynder
07. september 2006 - 09:16 #7
Herligt, tak for hjælpen...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester