html (webpagina info) string to data

Status
Niet open voor verdere reacties.

rvt1982

Gebruiker
Lid geworden
10 aug 2011
Berichten
156
Hallo allemaal,

Ik zit al dagen te klooien over iets simpels, maar ik loop hiermee vast..
ik werk al met .indexof en count enz, maar er zitten te veel variabelen in qua lengte (en het ziet er niet uit qua code lol)
Het kan heel makkelijk, maar ik zit naar mijn idee helemaal verkeerd te kijken...

Wat probeer ik te bereiken:
ik wil van een html string (zie een stukje string hieronder bepaalde informatie eruit filteren, zoals:
- Laatst gewijzigd: 16 december 2016
- Naam: P.L. (Pascal Leon) Pieterse
- Telefoonnummer: 06-00000000
- Geboortedatum: 01-07-1968
- Geslacht: Man
- Straat: Straatnaam 4
- Postcode: 1234AA
- Plaats: Plaats
- E-mailadres: Mailadres@gmail.com
- persoonlijkePresentatie: een heleboel tekst staat hier..
- Competenties: Klantgericht werken, Succesvol willen zijn, Plannen en organiseren, Anderen aansturen, Werken volgens de regels, Kostenbewust zijn, enz enz enz...

Ik denk dat het beste is om naar de ID naam te zoeken en vanaf daar de info eruit te halen, maar met count/lengte werkt dit niet.
omdat bijvoorbeeld een straatnaam korter of langer kan zijn.. ook zitten er veel aanhalingstekens in de tekst (html)

wie o wie kan mij hiermee op gang helpen???

Alvast bedankt :thumb:

VB.net
Code:
Dim str As String = WebBrowser1.DocumentText

String info: (DocumentText)
Code:
                    <h4>Facilitaire duizenpoot</h4>
                    <span class="meta fixed">
                        Referentie: #3330442
                    </span>
                    <span class="meta">
                        Laatst gewijzigd: 16 december 2016
                    </span>
                </div>
            </div>

            <div class="s-resume cv-personal-details">
                <div class="s-resume-header">
                    <h3>
                        Persoonlijke gegevens
                    </h3>
                </div>
                <div class="s-resume-content">
                    

    <div id="persoonlijkeGegevens_naam" class="first">
        <div class="label">Naam</div>
        <div class="value">
            P.L.&nbsp;
            Pascal Leon&nbsp;
            Pieterse
        </div>
    </div>

    <div id="persoonlijkeGegevens_telefoonnummer">
        <div class="label">Telefoonnummer</div>
        <div class="value">0600000000</div>
    </div>

    <div id="persoonlijkeGegevens_geboortedatum">
        <div class="label">Geboortedatum</div>
        <div class="value">01-07-1968</div>
    </div>
    <div id="persoonlijkeGegevens_geslacht" class="first">
        <div class="label">Geslacht</div>
        <div class="value">Man</div>
    </div>
    <div id="persoonlijkeGegevens_straat">
        <div class="label">Straat</div>
        <div class="value">Straatnaam&nbsp;4&nbsp;
            </div>
    </div>
    <div id="persoonlijkeGegevens_postcode">
        <div class="label">Postcode</div>
        <div class="value">1234AA</div>
    </div>
    <div id="persoonlijkeGegevens_plaats">
        <div class="label">Plaats</div>
        <div class="value">Plaats</div>
    </div>
    
    <div id="persoonlijkeGegevens_email">
        <div class="label">E-mailadres</div>
        <div class="value">Mailadres@gmail.com</div>
    </div>

                </div>
            </div>
            
                <div class="s-resume cv-personal-presentation">
                    <div class="s-resume-header">



<div id="persoonlijkePresentatie">
    <div id="persoonlijkePresentatie_persoonlijkepresentatie">
        
            <blockquote>
                een heleboel tekst staat hier..
            </blockquote>
        
    </div>
</div>






<div id="" class="formrow">
    
        
        
            <h4>Competenties</h4>
        
    
</div>
                        <div class="label margin-right s-text-bold">Klantgericht werken</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Succesvol willen zijn</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Plannen en organiseren</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Anderen aansturen</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Werken volgens de regels</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Kostenbewust zijn</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Omgaan met verandering</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Anderen overtuigen en beïnvloeden</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Kwaliteit leveren</div>
                    
                <div class="value"></div>
            
                        <div class="label margin-right s-text-bold">Samenwerken en overleggen</div>
 
kun je de informatie niet in JSON of XML formaat uit het systeem krijgen? Dat zou al veel schelen.

Voor de rest kun je dit deels oplossen met regular expressions, maar de opmaak is werkelijk verschrikkelijk. De opmaak is duidelijk gemaakt voor een javascript parser. Je hebt wat mij betreft 2 keuzes als je geen JSON of XML kan krijgen: een javascript pre-parser gebruiken (waarschijnlijk onhandig in dit project als je weinig ervaring hebt) of een aantal regex gebruiken.
 
Helaas is JSON en XML geen optie, dus ik blijft zitten met de "verschrikkelijke" opmaak hahaha.
Regex heeft mij alweer een stuk op weg geholpen, maar helaas niet opgelost.. op een of andere manier krijg ik niet de gegevens van bijvoorbeeld de straatnaam..

zou je mij een voorbeeld kunnen laten zien dat ik alleen de straatnaam krijg?

Alvast bedankt!!
 
Als ik alle enters weghaal en de regex erover haal krijg ik ze allemaal:

<div.+?value">(.+?)<\/div>

Straatnaam kan natuurlijk ook, maar dit zou gewoon een lijstje met alle 8 items moeten geven. Wel dus even zorgen dat er geen enters instaan zodat de query over de hele string loopt
 
Laatst bewerkt:
De waarden moet ik los hebben, gezien deze variabel zijn (soms wel aanwezig, soms ook niet).

Is er ook een trucje om bij de 2e "</div>" te komen?
Als ik deze code gebruik, dan pakt deze de eerste, en moet eigenlijk bij de 2e hebben..
(?<=persoonlijkeGegevens_straat)(.*?)(?=</div>)

Nog mooier zou zijn, op "persoonlijkeGegevens_straat)" zoeken en de waarde tussen ""value">" en /div pakken (die er direct na komt.
maar dit lijkt tot nu toe voor mij onmogelijk...

Code:
    <div id="persoonlijkeGegevens_straat">
        <div class="label">Straat[COLOR="#00FF00"]</div>[/COLOR]
        <div class="value">Straatnaam&nbsp;4&nbsp;
            [COLOR="#00FF00"]</div>[/COLOR]
 
Deze werkt voor mij:

<div id="persoonlijkeGegevens_straat.+?value">(.+?)<\/div>

zelfde als boven, maar iets specifieker. let wel: 1 string zonder enters
 
Kan het niet met een DOMDocument met .Selectnodes via een XPath?
 
@alphamax: nope alleen via de html code ;-)

@wampier:
weer een stapje dichterbij! maar ik krijg 2 verschillende resultaten.
1. via de Visual Studio
2. online regexhero.net/tester

De resultaten bij de regexhero tester wil ik hebben, maar wat doe ik fout?

Code:
        Dim findtext As String = "persoonlijkeGegevens_straat.+?value.>(.*?)</div>"
        Dim myregex As String = RichTextBox1.Text 'HTML code
        myregex = myregex.Replace(vbCr, "").Replace(vbLf, "").Replace("&nbsp;", " ")

        Dim doregex As MatchCollection = Regex.Matches(myregex, findtext)
        Dim matches As String = ""

        For Each match As Match In doregex
            matches = matches + match.ToString + Environment.NewLine
        Next

        RichTextBox2.Text = matches.ToString 'Results

Results:
Code:
persoonlijkeGegevens_straat">        <div class="label">Straat</div>        <div class="value">Straatnaam 4 </div>

Via de online regexhero.net/tester:
Code:
Straatnaam 4
 
Voor inspiratie google "regex html tags".
 
Ik ben ooit ook html met regex gaan scrapen maar de code wordt zo'n gedrocht, als ik het nu nodig heb gebruik ik HtmlAgilityPack en LINQ ik gewoon naar de nodes (xpath kan ook maar ik gebruik liever LINQ).

> zoek div met id 'persoonlijkeGegevens_straat'
> zoek child div met class 'value'
> get innertext



https://www.nuget.org/packages/HtmlAgilityPack
 
Die is voor mij helemaal nieuw..
heb je hiervan toevallig ook een voorbeeld? ik zou niet weten hoe ik hiermee moet beginnen :p

zo iets simpels, maar dit houd dagen bezig.. :shocked:

thnx
 
probleem gevonden, maar nog niet de oplossing :d

Deze match de characters
persoonlijkeGegevens_straat.+?value.>(.*?)</div>

en met haal ik alles op, maar ik niet de matching characters hebben, maar de matching groups...
Dim doregex As MatchCollection = Regex.Matches(myregex, findtext)

of te wel, alleen deze
(.*?)

maar hoe ???
 
Laatst bewerkt:
Je kunt de agilitypack dll toevoegen aan je project door rechtermuisknop op je project te klikken en dan 'manage nuget packages' en deze dan te zoeken en te installeren. Daarna kun je er gebruik van maken.

Ik heb voor het voorbeeld (console app) een stuk van je html gepakt en in een bestandje gezet dat ik laad ipv waar je het normaal van download maar uiteindelijk krijg je toch de source als string binnen.

Dan maak ik een htmldocument 'document' en laad de htmlsource erin. Daarna kun je met LINQ gewoon naar tags zoeken die bepaalde attributes hebben bijvoorbeeld. De gegevens staan allemaal in een 'div' met een class 's-resume-content' dus dan haal ik die node op, en daarna gebruik ik deze node om daar verder in te zoeken. Omdat deze allemaal dezelfde structuur hebben alleen een andere 'id' waarde kun je ook een methode maken de een waarde inneemt van het id om de rest op te halen zodat je niet alles dubbel hoeft te doen.

Ik haal alle opgehaalde waarde door 'WebUtility.HtmlDecode' voor de &nbsp; bijvoorbeeld, je kunt het resultaat ook nog 'trimmen' door whitespace ervoor en erachter weg te halen mocht dat meekomen.

Een stuk overzichtelijker en dus ook makkelijker te onderhouden. (let wel: in je daadwerkelijke code wil je wel wat null checks etc toevoegen)

(ik heb get in C# gedaan en dan naar VB convert, hoop dat het duidelijk is)

[CPP]Imports System.IO
Imports System.Linq
Imports System.Net
Imports HtmlAgilityPack

Namespace AgilityDemo
Class Program
Private Shared Sub Main(args As String())
Dim source = File.ReadAllText("html/resume.html")

Dim document = New HtmlDocument()
document.LoadHtml(source)

Dim contentNode = document.DocumentNode.Descendants("div").First(Function(x) x.GetAttributeValue("class", "").Equals("s-resume-content"))


Dim nameNode = contentNode.Descendants("div").First(Function(x) x.GetAttributeValue("id", "").Equals("persoonlijkeGegevens_naam"))
Dim valueNode = nameNode.Descendants("div").First(Function(x) x.GetAttributeValue("class", "").Equals("value"))

Dim name = WebUtility.HtmlDecode(valueNode.InnerHtml)


Dim phone = GetValue(contentNode, "persoonlijkeGegevens_telefoonnummer")
Dim dob = GetValue(contentNode, "persoonlijkeGegevens_geboortedatum")
Dim gender = GetValue(contentNode, "persoonlijkeGegevens_geslacht")
Dim street = GetValue(contentNode, "persoonlijkeGegevens_straat")
Dim zip = GetValue(contentNode, "persoonlijkeGegevens_postcode")
Dim town = GetValue(contentNode, "persoonlijkeGegevens_plaats")
Dim email = GetValue(contentNode, "persoonlijkeGegevens_email")

Console.Read()
End Sub

Private Shared Function GetValue(contentNode As HtmlNode, id As String) As String
Dim valueNode = contentNode.Descendants("div").First(Function(x) x.GetAttributeValue("id", "").Equals(id)).Descendants("div").First(Function(x) x.GetAttributeValue("class", "").Equals("value"))

Return WebUtility.HtmlDecode(valueNode.InnerHtml)
End Function
End Class
End Namespace[/CPP]


HTML:
<div class="s-resume cv-personal-details">
    <div class="s-resume-header">
        <h3>
            Persoonlijke gegevens
        </h3>
    </div>
    <div class="s-resume-content">
        <div id="persoonlijkeGegevens_naam" class="first">
            <div class="label">Naam</div>
            <div class="value">
                P.L.&nbsp;
                Pascal Leon&nbsp;
                Pieterse
            </div>
        </div>
        <div id="persoonlijkeGegevens_telefoonnummer">
            <div class="label">Telefoonnummer</div>
            <div class="value">0600000000</div>
        </div>
        <div id="persoonlijkeGegevens_geboortedatum">
            <div class="label">Geboortedatum</div>
            <div class="value">01-07-1968</div>
        </div>
        <div id="persoonlijkeGegevens_geslacht" class="first">
            <div class="label">Geslacht</div>
            <div class="value">Man</div>
        </div>
        <div id="persoonlijkeGegevens_straat">
            <div class="label">Straat</div>
            <div class="value">Straatnaam&nbsp;4&nbsp;
            </div>
        </div>
        <div id="persoonlijkeGegevens_postcode">
            <div class="label">Postcode</div>
            <div class="value">1234AA</div>
        </div>
        <div id="persoonlijkeGegevens_plaats">
            <div class="label">Plaats</div>
            <div class="value">Plaats</div>
        </div>

        <div id="persoonlijkeGegevens_email">
            <div class="label">E-mailadres</div>
            <div class="value">Mailadres@gmail.com</div>
        </div>

    </div>
</div>
 
ja ja dat is hem
100% werkend gekregen!

Ik zal/moet inderdaad nog de null checks toevoegen en nog even verder verdiepen in LINQ en node (gezien ik dit niet zo vaak gebruik) :thumb:

Super bedankt!
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan