Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JS]xml-tree van html pagina opbouwen

Pagina: 1
Acties:

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik moet van een internetpagina het laatste nieuws afhalen, en in een andere pagina tonen. Helaas is deze pagina niet server-side dynamisch opgebouwd, dus moet dit nieuws dmv javascript ingeplakt worden. De pagina wordt een kloon van http://studenten.tudelft.nl. Hier zie je dat "Laatste nieuws" wordt gegenereerd door een javascript wat een rss feed parsed.

Helaas heeft de bron-pagina waar ik het nieuws vandaan moet halen geen rss feed. Ik moet dus de html filteren. De pagina waar ik de html uit moet knippen is deze: http://www.tudelft.nl/liv...844b-5b271aeec64a&lang=nl
offtopic:
Ik moet dus het nieuwsbericht "Delftse onderzoekers ontrafelen de werking van de fiets" t/m "Lustrumsymposium TU Delft “Sustainable Solutions, focus on Africa”" knippen uit de pagina


Wat ik dus heb gedaan is dit als een scriptje toegevoegd:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var requestUri = "http://www.tudelft.nl/live/pagina.jsp?id=25d410c9-3dd2-4579-844b-5b271aeec64a&lang=nl";
var xmlHttp;

function loadNews(){
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    xmlHttp = createRequest();
    if(!xmlHttp){
        return;
    }
    
    var requestValue = sendRequest();
    requestValue = stripRequest(requestValue);
}

function createRequest(){
    var xmlHttp;
    try {
        // Firefox, Opera 8.0+, Safari
        xmlHttp=new XMLHttpRequest();
    }catch (e){
        // Internet Explorer
        try{
            xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
        }catch (e){
            try{
                xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
            }catch (e){
                xmlHttp = false;
            }
        }
    }
    return xmlHttp;
}

function sendRequest(){
    xmlHttp.onreadystatechange=function(){
        if(xmlHttp.readyState==4){
             return xmlHttp.responseXML;
        }
    }
    xmlHttp.open("GET",requestUri,true);
    xmlHttp.overrideMimeType('text/xml');
    xmlHttp.send(null);
}

function stripRequest(xmlObj){
    var obj = xmlObj.getElementById("document0");
    /*
    doe hier iets met obj zodat alleen de eerste vijf nieuws items weergegeven worden
    */
    return obj;
}
Mijn insteek was om de pagina als xml-tree in te laden, en dan de html in de functie stripRequest uit te filteren:
  • Eerst alles om de div met id "document0" weg te gooien (dat bevat voor mij niet-interessante info).
  • Daarna pak ik van de serie <strong></strong><em></em><p></p> de eerste vijf items
Nu is alleen de bron-pagina geen xml of xhtml pagina, en is er dus een verkeerde xml-tree. Het gaat eigenlijk al fout bij de doctype, omdat daar volgens html4.01 een tag wordt aangemaakt, maar volgens xhtml/xml die tag niet wordt afgesloten...

Hoe kan ik simpel en liefst via dom dit oplossen? Ik krijg nu namelijk de volgende error:
Error: syntax error
Source File: http://www.tudelft.nl/live/pagina.jsp?id=25d410c9-3dd2-4579-844b-5b271aeec64a&lang=nl
Line: 3, Column: 62
Source Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">-------------------------------------------------------------^
Graag geen commentaar dat ik maar xml feeds moet gaan produceren, want dat is uitgezocht, en echt niet mogelijk :)

Even nog een samenvatting:
Ik wil op zo'n soort pagina de bovenste zes nieuws items van deze pagina tonen, wat met javasscript ingeladen moet worden. De bron-pagina is echter een html pagina, en die krijg ik niet goed geparsed. Hoe los ik dit op?

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Je probeert iets als XML te parsen dat geen XML is, logisch dat je dat een syntax error oplevert. Zelfs al zou het wellformed XHTML zijn (dat is schaars op het web overigens) dan nog kan je niet alle DOM methods gebruiken die je in HTML kan gebruiken. Zo heeft een ID attribuut geen betekenis in een XML DOM en daarom is er geen getElementById method.

Je zal dus een HTML parser moeten gebruiken, of string-methods toepassen op de responseText.

Bedenk overigens dat XHR normaliter geen cross-domain requests kan doen; je gebruikt hier de PrivilegeManager voor Firefox om het daar mogelijk te maken maar dat zal in andere browsers geen effect hebben.

[ Voor 18% gewijzigd door crisp op 20-09-2007 13:48 ]

Intentionally left blank


  • Comgenie
  • Registratie: Oktober 2005
  • Laatst online: 23:28

Comgenie

Soms heb je dat

Zo te zien kan je beter REGEX gebruiken ( http://www.google.nl/search?hl=nl&q=regex&meta= ) , daarmee kan je zulke dingen 'eruit halen'. Het is wel even lastig om te begrijpen maar dan heb je ook wat. In JS en de meeste andere talen zijn er als het goed is wat regex functies.

[ Voor 10% gewijzigd door Comgenie op 20-09-2007 13:54 ]

No animals were harmed in the making of this comment.


  • user109731
  • Registratie: Maart 2004
  • Niet online
Als de server PHP ondersteunt kun je ook serverside de pagina laden, daar parsen en cachen, en dat naar de client sturen. Dan heb je a) geen last meer van cross-domain issues, b) het is sneller (omdat je het makkelijk kunt cachen voorkom je requests), en c) niet van JS afhankelijk :)

  • mithras
  • Registratie: Maart 2003
  • Niet online
crisp schreef op donderdag 20 september 2007 @ 13:46:
Je probeert iets als XML te parsen dat geen XML is, logisch dat je dat een syntax error oplevert.
Zo'n idee had ik dus al :p
Zelfs al zou het wellformed XHTML zijn (dat is schaars op het web overigens) dan nog kan je niet alle DOM methods gebruiken die je in HTML kan gebruiken. Zo heeft een ID attribuut geen betekenis in een XML DOM en daarom is er geen getElementById method.

Je zal dus een HTML parser moeten gebruiken, of string-methods toepassen op de responseText.
Mm, dat zal dan regexen gaan worden op responseText ben ik bang :/
Bedenk overigens dat XHR normaliter geen cross-domain requests kan doen; je gebruikt hier de PrivilegeManager voor Firefox om het daar mogelijk te maken maar dat zal in andere browsers geen effect hebben.
Ja, daar was ik al achter. Het gaat om een domein medewerkers.tudelft.nl wat dus informatie van tudelft.nl moet afhalen. Iets wat nog steeds problemen zal opleveren, maar ik zou het graag werkend willen hebben op IE6+7 + Firefox en misschien Safari (als ik iemand te pakken krijg die voor mij wil testen).
Comgenie schreef op donderdag 20 september 2007 @ 13:52:
Zo te zien kan je beter REGEX gebruiken ( http://www.google.nl/search?hl=nl&q=regex&meta= ) , daarmee kan je zulke dingen 'eruit halen'. Het is wel even lastig om te begrijpen maar dan heb je ook wat. In JS en de meeste andere talen zijn er als het goed is wat regex functies.
Ik ben bekend met regexen ja :) Een hels langzame klus zal dat worden, maar daar ga ik wel uitkomen, thanx :)
JanDM schreef op donderdag 20 september 2007 @ 14:02:
Als de server PHP ondersteunt kun je ook serverside de pagina laden, daar parsen en cachen, en dat naar de client sturen. Dan heb je a) geen last meer van cross-domain issues, b) het is sneller (omdat je het makkelijk kunt cachen voorkom je requests), en c) niet van JS afhankelijk :)
Nope, als er iets serverside mogelijk was, had ik dat wel gedaan. Het is een closed-source cms (helaas) wat ook nog op een Windows server draait: iets waar ik dus totaal niet in thuis ben. Sowieso geen optie dus :)

Ik ga morgen dan eens aan de slag met regexen: kijken wat ik ermee kan uithalen :)

  • mithras
  • Registratie: Maart 2003
  • Niet online
mithras schreef op donderdag 20 september 2007 @ 15:00:
Ik ben bekend met regexen ja :) Een hels langzame klus zal dat worden, maar daar ga ik wel uitkomen, thanx :)
Goed, niet helemaal dus....

Ik wil de volgende html pagina matchen:
code:
1
2
3
4
5
6
7
8
9
10
... hele ... hoop ... onzin (zo'n 5500 karakters)
<h1>Laatste nieuws TU Delft</h1>
<strong>New Delft material concept for aircraft wings could save billions</strong>
<em> -24&nbsp;September&nbsp;2007</em>
<p>Building aircraft wings with a special aluminium fibre combination makes them nearly immune to metal fatigue. The application of this technology, partly developed at TU Delft, will lead to substantial savings. The unusual qualities of this special material (called CentrAl, an abbreviation of Central Reinforced Aluminium) can make a significant contribution to the development of truly energy-efficient, &lsquo;green&rsquo; aircraft. Lower fuel consumption and reduction of maintenance costs could lead to worldwide savings as high as &euro;75 billion. <br>
<strong><a href="http://www.tudelft.nl/live/pagina.jsp?id=a7e23c9d-a6b2-4dbb-8ea5-c7601acbbd1e&lang=en">read more</a></strong>
</p>
... dit ... 5 keer ... herhaald....
<h1>Agenda</h1>
... nog ... veel ... meer ... onzin....
Du wil ik dus vanaf de eerste <strong> na de <h1> tag tot de laatste </p> van de <h1>Agenda</h1>

De algemene opbouw van zo'n nieuws item is:
code:
1
2
3
4
<strong>Titel</strong>
<em>date</em>
<p>Content<br>
<strong>Lees meer</strong></p>
Zoiets komt 5 keer voor tussen de "Laatste nieuws" en "Agenda". Daarvoor heb ik de volgende regex bedacht:
^<h1>(Latest news TU Delft|Laatste nieuws TU Delft)<\/h1>(.*?)<h1>Agenda<\/h1>$

In deze context:
JavaScript:
1
2
3
4
5
6
7
8
function stripRequest(text){
    var regexObj = new RegExp("^<h1>(Latest news TU Delft|Laatste nieuws TU Delft)<\/h1>(.*?)<h1>Agenda<\/h1>$");
    var text = regexObj.exec(text);
    if(text)
        return text[0];
    else
        return null;
}
Ik heb het regexObj en het feit dat ik het 0e element moet pakken van www.regular-expressions.info. Maar hij returned dus fijn null, want de regex komt niet uit, of het object "werkt" niet. Ik zit hier nu al tijden mee te pielen om het recht te zetten, maar ik kan niet veel meer info vinden over regexen en javascript dan op regular-expressions.info.

Wie o wie heeft een gouden tip om te zorgen dat ik deze grote html pagina wel goed kan uitsplitsen in wat ik wil? De firefox error-console geeft namelijk geen errors, iets wat er bij mij op duidt dat de regexObj() wel werkt, maar de regex zelf dus niet goed is...

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 00:51

crisp

Devver

Pixelated

Je vergeet de s-modifier, op deze manier matched de . (dot) niet op newlines ;)

edit: JS heeft natuurlijk geen s-modifier 8)7

this should work though:
JavaScript:
1
var regexObj = /<h1>(Latest news TU Delft|Laatste nieuws TU Delft)<\/h1>([\s\S]*?)<h1>Agenda<\/h1>/; 

(even een literal genomen, anders moet ik dubbel gaan escapen).

[ Voor 62% gewijzigd door crisp op 27-09-2007 16:56 ]

Intentionally left blank


  • mithras
  • Registratie: Maart 2003
  • Niet online
Oke, ik liep te pielen en proberen, kom ik er nu achter wat je bedoelt met dubbel escapen 8)7

Ik krijg de teksten eindelijk eruit. Super bedankt voor je hulp crisp :*)
Pagina: 1