Trädvy Permalänk
Medlem
Plats
Uddevalla
Registrerad
Nov 2002

Simple HTML dom parser

Hej!

Blir tokig på detta, men hur i hela fridens namn skrapar jag en tabell men hjälp av http://simplehtmldom.sourceforge.net?

Då menar jag:

Steg1 Hämta thead, med tillhörande th
Steg2 Hämta tr, med respektive td
Steg3 Klart!

Jag är alldeles för trög märker jag eftersom att manualen ändå är rätt bra http://simplehtmldom.sourceforge.net/manual.htm Googlar man så får man endel träffar, men likförbannat fixar jag det inte.

Såhär är det förväntade resultat:

+-------------+--------+-------+-------+-------+-------+--------+--------+---------+ | Aktie | Senast | +/- | % | Köp | Sälj | Högst | Lägst | Omsatt | +-------------+--------+-------+-------+-------+-------+--------+--------+---------+ | AAK AB | 549,90 | ..etc | ..etc | ..etc | ..etc | ..etc | ..etc | ..etc | | ABB LTD | 149.80 | ..etc | ..etc | ..etc | ..etc | ..etc | ..etc | ..etc | | and so on.. | | | | | | | | | +-------------+--------+-------+-------+-------+-------+--------+--------+---------+

Är inte linux en billig kopia av ms-dos?

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Okt 2010
Skrivet av akn3:

Hej!
[...]

Vad har du för kod i dagsläget och vilken sida försöker du skrapa ifrån?

Dator, MOBO: Asus X99-A, CPU: Intel I7 6800k (3.4GHz), GPU: Asus GTX 1080 Strix, RAM: 4x8GB Corsair Vengeance LPX 2400MHz, OS-HDD: Intel 750 PCIe 400GB, PSU: EVGA SuperNOVA G2 850W

Trädvy Permalänk
Medlem
Plats
Uddevalla
Registrerad
Nov 2002

@Klorixx:

require('simple_html_dom.php'); $html = file_get_html($url); // remove all image foreach($html->find('img') as $e) $e->outertext = ''; // Remove a attribute, set it's value as null! foreach($html->find('a') as $e) $e->href = null; echo '<table>'; echo '<thead>'; foreach($html->find('thead th') as $e){ echo '<th>'.$e->plaintext .'</th>'; } echo '</thead>'; foreach($html->find('tr th') as $e){ echo $e->plaintext; } echo '</table>'; ?>

Såhär ser tabellen ut: http://pastebin.com/rMhVCd9X Den är så jäkla stor så jag har kortat ner den i binnen.

Är inte linux en billig kopia av ms-dos?

Trädvy Permalänk
Webbutvecklare
Moderator
Plats
::1
Registrerad
Dec 2002

@akn3: Rekommenderar att du löser uppgiften med XPath istället för bibliotek som "Simple" HTML DOM, de fungerar sällan särskilt väl och i längden kommer det kosta mer än det smakar. I PHP kommer du åt XPath via t.ex. DOMDocument + DOMXPath.

$doc = new \DOMDocument(); if($doc->loadHTML($html)) { $xpath = new \DOMXPath($doc); // Fråga efter en tabell med ID=kurstabell, sedan alla thead/tr/th under denna: foreach($xpath->query("//table[@id='kurstabell']/thead/tr/th") as $header) { // ... } // Upprepa frågan efter tabellen, men denna gång efter alla rader i dess tbody: foreach($xpath->query("//table[@id='kurstabell']/tbody/tr") as $row) { // För varje rad behöver vi sedan hitta varje cell, så vi använder raden // som context och förankrar frågan efter celler mot denna: foreach($xpath->query("./td", $row) as $cell) { // ... } } }

libxml_use_internal_errors(true); $doc = new \DOMDocument(); if($doc->loadHTML($html)) { $result = new \DOMDocument(); $result->formatOutput = true; $table = $result->appendChild($result->createElement("table")); $thead = $table->appendChild($result->createElement("thead")); $tbody = $table->appendChild($result->createElement("tbody")); $xpath = new \DOMXPath($doc); $newRow = $thead->appendChild($result->createElement("tr")); foreach($xpath->query("//table[@id='kurstabell']/thead/tr/th[position()>1]") as $header) { $newRow->appendChild($result->createElement("th", trim($header->nodeValue))); } foreach($xpath->query("//table[@id='kurstabell']/tbody/tr") as $row) { $newRow = $tbody->appendChild($result->createElement("tr")); foreach($xpath->query("./td[position()>1]", $row) as $cell) { $newRow->appendChild($result->createElement("td", trim($cell->nodeValue))); } } echo $result->saveXML($result->documentElement); }

Exempel: Skapa ny tabell

Abstractions all the way down.

Trädvy Permalänk
Medlem
Plats
Uddevalla
Registrerad
Nov 2002

@Tunnelsork:

print_r(var_dump($result->saveXML($result->documentElement)),true);

Ger mig svar

string(58) " "

Inga felmeddelanden i php_error log
I övrigt inga som helst livstecken.

print_r($result);

ger mig:

DOMDocument Object ( [doctype] => [implementation] => (object value omitted) [documentElement] => (object value omitted) [actualEncoding] => [encoding] => [xmlEncoding] => [standalone] => 1 [xmlStandalone] => 1 [version] => 1.0 [xmlVersion] => 1.0 [strictErrorChecking] => 1 [documentURI] => [config] => [formatOutput] => 1 [validateOnParse] => [resolveExternals] => [preserveWhiteSpace] => 1 [recover] => [substituteEntities] => [nodeName] => #document [nodeValue] => [nodeType] => 9 [parentNode] => [childNodes] => (object value omitted) [firstChild] => (object value omitted) [lastChild] => (object value omitted) [previousSibling] => [attributes] => [ownerDocument] => [namespaceURI] => [prefix] => [localName] => [baseURI] => [textContent] => )

Är inte linux en billig kopia av ms-dos?

Trädvy Permalänk
Webbutvecklare
Moderator
Plats
::1
Registrerad
Dec 2002

@akn3: Du behöver inte anropa print_r och var_dump i följd så där. Det räcker med var_dump (du bör använda den eftersom att den inkluderar typinformation), men om du av någon anledning behöver använda print_r så var försiktig med dess andra parameter; just nu har du bett den att returnera resultatet istället för att skriva ut det, men sedan gör du inget med det.

Har du problem att se innehållet i variablen så kom ihåg ditt sammanhang. Den innehåller något som ser ut som HTML, och såvida du inte har sagt något annat till din webbläsare så kommer den göra sitt bästa för att tolka hela svaret så innan det presenteras för dig; prova att granska källan eller använda en annan Content-Type.

<?php header("Content-Type: text/html"); var_dump("<b></b>"); // Visas som: // string(7) ""

Exempel: text/html

<?php header("Content-Type: text/plain"); var_dump("<b></b>"); // Visas som: // string(7) "<b></b>"

Exempel: text/plain

Här är exemplet ovan, oförändrat förutom att det tar din pastebin som källa:
http://codepad.viper-7.com/d7tkLs

(Tar det tid att ladda så försök igen eller kopiera till din egen server)

Abstractions all the way down.

Trädvy Permalänk
Medlem
Plats
Uddevalla
Registrerad
Nov 2002

<?php $html = file_get_contents("http://localhost/index.html"); libxml_use_internal_errors(true); $doc = new \DOMDocument(); if($doc->loadHTML($html)) { $result = new \DOMDocument(); $result->formatOutput = true; $table = $result->appendChild($result->createElement("table")); $thead = $table->appendChild($result->createElement("thead")); $tbody = $table->appendChild($result->createElement("tbody")); $xpath = new \DOMXPath($doc); $newRow = $thead->appendChild($result->createElement("tr")); foreach($xpath->query("//table[@id='kurstabell']/thead/tr/th[position()>1]") as $header) { $newRow->appendChild($result->createElement("th", trim($header->nodeValue))); } foreach($xpath->query("//table[@id='kurstabell']/tbody/tr") as $row) { $newRow = $tbody->appendChild($result->createElement("tr")); foreach($xpath->query("./td[position()>1]", $row) as $cell) { $newRow->appendChild($result->createElement("td", trim($cell->nodeValue))); } } echo $result->saveXML($result->documentElement); } ?>

Notera $html = file_get_contents("http://localhost/index.html"); Verkar vara det som ställde till problem för mig. Men nu till ett annat problem!

De namn som innehåller ett "och tecken" (& , ampersand, &amp;) syns inte i den första kolumnen, i den första <td> i den representerade <tr> raden. Alltså hela stringen är borta, inte bara själva tecknet.

Vad kan problemet vara?

EDIT

Kommenterade raden libxml_use_internal_errors(true); så fick jag ett felmeddelande Warning (2): DOMDocument::createElement(): unterminated entity reference som jag följde hit

raden
$newRow->appendChild($result->createElement("td", trim($cell->nodeValue)));

blev till
$newRow->appendChild($result->createElement("td", trim(htmlentities($cell->nodeValue))));

Om detta är rätt är jag dock osäker på! men det löste problemet med det saknade innehållet!
(Dock får jag nu felmeddelande: PHP Warning: DOMDocument::loadHTML(): Tag footer invalid in Entity, line: 9393)

Är inte linux en billig kopia av ms-dos?