[PHP] file_get_contents en preg_match troubles...

Pagina: 1
Acties:

Onderwerpen


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Hoi,

Ik wil voor ons thuisnetwerk een mooie overzichtspagina maken met status van diverse apparaten. Zo wil ik voor de printer bijv. uitlezen hoeveel toner er nog beschikbaar is.

De printer heeft een webpagina, met daarin een frame waar de gegevens inzitten: 192.168.1.251/hp/device/info_deviceStatus.html

In dat frame zit de volgende code, met daarin het tonerniveau (43%)
HTML:
1
2
3
<tr><td width = "25%"><font class="if">
    Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;43%
    </font></td></tr>


Ik wil die "43" er dus uithalen. Dit probeer ik met onderstaand script:
PHP:
1
2
3
4
5
6
7
8
9
<?php

$content = file_get_contents('http://192.168.1.251/hp/device/info_deviceStatus.html');

preg_match('#<font class="if"> 
    Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(.*)</font>#', $content, $match);
$tonerniveau = $match[1];
echo "Tonerniveau: $toner\n";
?>


maar het werkt niet, ik zie alleen maar "Tonerniveau:" staan.


Echter, dit script:
PHP:
1
2
3
4
5
6
7
8
<?php

$content = file_get_contents('http://www.sparkfun.com/commerce/product_info.php?products_id=9279');

preg_match('#<span class=price>(.*)</span>#', $content, $match);
$price = $match[1];
echo "Price: $price\n";
?>


Werkt wel, die haalt netjes de prijs "0.50" op.


Ter informatie: De printerpagina is onbeveiligd, zodra ik het adres bovenaan in deze post open dan zie ik gelijk het tonerniveau. Ik hoef dus niet in te loggen.

Wat doe ik verkeerd dat het niet werkt?

[ Voor 8% gewijzigd door ThinkPad op 30-09-2012 13:56 ]


  • eek
  • Registratie: Februari 2001
  • Laatst online: 06-04-2020

eek

@MagickNET

$tonerniveau = $match[1];
echo "Tonerniveau: $toner\n";

Skill is when luck becomes a habit.


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Met

code:
1
2
$tonerniveau = $match[1]; 
echo "Tonerniveau: $tonerniveau\n";


werkt het ook niet.

Verwijderd

Hint: je patroon beschrijft meerdere regels.

  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 15:31

DataGhost

iPL dev

Nog een hint: je matcht wel erg specifiek, sommige tekenreeksen kan je beter met klassen matchen

  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Ik heb nu dit
PHP:
1
preg_match('#&nbsp;(.*)%#', $content, $match);
maar dat werkt ook niet.

Het tonerniveau staat niet echt in een bepaalde klasse helaas.

Ik weet trouwens wel zeker dat het aan dat preg_match stukje ligt. Als ik namelijk
PHP:
1
echo $content;
doe dan zie ik de printer status pagina. Dat stuk gaat wel goed dus.

[ Voor 35% gewijzigd door ThinkPad op 30-09-2012 14:18 ]


  • DataGhost
  • Registratie: Augustus 2003
  • Laatst online: 15:31

DataGhost

iPL dev

Ik bedoel een character class, geen HTML class-attribuut.

edit:
beide hints zijn nog steeds geldig trouwens Oeps. Bovenstaande had inderdaad moeten werken en onderstaande beter. Je wilt eigenlijk nog wat context eromheen hebben en dan gaan beide hints wel weer op, maar het zou best zo kunnen zijn dat dit goed genoeg werkt aangezien die pagina nauwelijks zal veranderen.

[ Voor 97% gewijzigd door DataGhost op 30-09-2012 14:29 ]


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Zoeken op character class zou toch zoiets als dit moeten zijn:
PHP:
1
preg_match('#&nbsp;([0-9,]+)%#', $content, $match);

  • Camulos
  • Registratie: Januari 2009
  • Laatst online: 02-12 14:50

Camulos

Stampert

ThinkPadd schreef op zondag 30 september 2012 @ 13:54:

In dat frame zit de volgende code, met daarin het tonerniveau (43%)
HTML:
1
2
3
<tr><td width = "25%"><font class="if">
    Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;43%
    </font></td></tr>


Ik wil die "43" er dus uithalen.
Wellicht een alternatieve oplossing zonder reguliere expressies. Onderstaande code is gebaseerd op een html-scraper die ik eerder heb gebruikt.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// get HTML
$content = file_get_contents('http://192.168.1.251/hp/device/info_deviceStatus.html');

// optionally 1: you can split (explode function) on <TR to iterate over each row 
// optionally 2: you can strip static content by str_replace function

// strip all HTML, leaving just "Black Cartridge     43%"
$stripped = strip_tags($content)

// trim egdes, no spaces at the front or end
$trimmed = trim($stripped);

// Explode, convert to array. Delimiter is a space
$arr = explode(" ", $trimmed); 

// return last element -> 43%
echo end($arr);

[ Voor 13% gewijzigd door Camulos op 30-09-2012 16:29 ]

Not just an innocent bystander


  • Emmeau
  • Registratie: Mei 2003
  • Niet online

Emmeau

All your UNIX are belong to us

PHP Simple HTML DOM Parser
Ik gebruik dit altijd om webpages te parsen.
Geen gemeut met reguliere expressies die wel of niet fout kunnen gaan (html pages zijn per definitie niet handig om te parsen met reguliere expressies, daar is al genoeg over geroepen).

If you choose to criticise you choose your enemies


Verwijderd

Emmeau schreef op zondag 30 september 2012 @ 16:51:
PHP Simple HTML DOM Parser
Ik gebruik dit altijd om webpages te parsen.
Geen gemeut met reguliere expressies die wel of niet fout kunnen gaan (html pages zijn per definitie niet handig om te parsen met reguliere expressies, daar is al genoeg over geroepen).
Gebruik dan meteen DomDocument :)

Werkt inderdaad veel fijner dan prutsen met regular expressions voor dit soort doeleinden.

  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Camulos schreef op zondag 30 september 2012 @ 16:26:
[...]


Wellicht een alternatieve oplossing zonder reguliere expressies. Onderstaande code is gebaseerd op een html-scraper die ik eerder heb gebruikt.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
// get HTML
$content = file_get_contents('http://192.168.1.251/hp/device/info_deviceStatus.html');

// optionally 1: you can split (explode function) on <TR to iterate over each row 
// optionally 2: you can strip static content by str_replace function

// strip all HTML, leaving just "Black Cartridge     43%"
$stripped = strip_tags($content)

// trim egdes, no spaces at the front or end
$trimmed = trim($stripped);

// Explode, convert to array. Delimiter is a space
$arr = explode(" ", $trimmed); 

// return last element -> 43%
echo end($arr);
Ziet er goed uit, maar werkt hetlaas niet. Op m'n linux (debian) webserver krijg ik een error 500, en op xampp onder m'n w7 pc zie ik alleen "Tonerniveau:"

Vervelende is dat er nog meer kolommen zijn die ook font class if hebben... voorbeeld:
HTML:
1
2
3
4
5
 <td width="50%" align="left"> <font class="if">
        hp LaserJet 1320 series
        </font>
        </td>
        </tr>


De DOM parsers van hierboven heb ik bekeken, maar volgens mij werken die beiden op html klassen, en daar heb ik dus meerdere van....

Voor het gemak even de html code van de pagina van de printer: http://pastebin.com/scN76vxz

[ Voor 7% gewijzigd door ThinkPad op 01-10-2012 18:18 ]


  • aaajeetee
  • Registratie: Augustus 2002
  • Laatst online: 29-11 11:21
Misschien een stom idee, maar waarom match je dan niet op "black cartridge"? Daarachter kan je (met regex of domxpath) het percentage vinden.

Edit: dus iets als 'black cartridge[meuk]([0-9]+)%'.

[ Voor 16% gewijzigd door aaajeetee op 01-10-2012 18:43 ]


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Gelukt!

PHP:
1
2
3
4
5
6
7
8
<?php 

$content = file_get_contents('http://192.168.1.251/hp/device/info_deviceStatus.html'); 

preg_match('#Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;([0-9]+)%#', $content, $match); 
$toner = $match[1]; 
echo "Tonerniveau: $toner\n%"; 
?>


Geeft:
Tonerniveau: 43 %

Ik snap dat een DOM parser waarschijnlijk beter is, maar dat kreeg ik zo 123 niet aan de praat. Iets voor de volgende keer dus.

[ Voor 3% gewijzigd door ThinkPad op 01-10-2012 18:52 ]


  • spone
  • Registratie: Mei 2002
  • Niet online
Moet je preg match niet pre- en appenden met / ?

Ofwel:

PHP:
1
preg_match('/#Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;([0-9]+)%#/', $content, $match)


edit: hmm werkt kennelijk al. Nevermind dan :)

[ Voor 13% gewijzigd door spone op 01-10-2012 18:57 ]

i5-14600K | 32GB DDR5-6000 | RTX 5070 - MacBook Pro M1 Pro 14" 16/512


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Verwijderd schreef op zondag 30 september 2012 @ 14:11:
Hint: je patroon beschrijft meerdere regels.
Zal ik voor de mensen die later dit topic tegenkomen dan maar de oplossing helemaal noemen zonder alleen maar te hinten? :P

http://php.net/manual/en/...cre.pattern.modifiers.php
Vooral interessant: modifier 2 en 3.
spone schreef op maandag 01 oktober 2012 @ 18:56:
Moet je preg match niet pre- en appenden met / ?

Ofwel:

PHP:
1
preg_match('/#Black Cartridge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;([0-9]+)%#/', $content, $match)


edit: hmm werkt kennelijk al. Nevermind dan :)
Nee, je markeert het begin en einde van de regexp met een delimiter. In dit geval dus de #. Welk karakter je kiest maakt voor PCRE geen fluit uit, als je maar twee keer hetzelfde karakter gebruikt.

[ Voor 40% gewijzigd door NMe op 01-10-2012 19:03 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Ik ga nog wel even verder stoeien, want ik heb ook het status veld:
HTML:
1
2
3
4
5
6
7
8
<td nowrap="nowrap">
<font class="clf">
Status: &nbsp;&nbsp </font>
<font class="if">
Printer Tray Is
Empty. Add Paper
 &nbsp;&nbsp;</font>
</td>
en daar zitten geen nummers in, dus die valt er met een regular expression niet makkelijk uit te halen.

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Waarom niet? Je weet dat het begint met "Status" en er wat achteraan komt. Alles tot aan </font> is vervolgens je waarde. Hoe is dat lastig?

edit:
Ah, het gaat om dat tweede stukje natuurlijk. Ook dat is toch niet lastig? Voldoet namelijk net zo hard aan een duidelijk patroon. ;)

[ Voor 32% gewijzigd door NMe op 01-10-2012 19:55 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • ThinkPad
  • Registratie: Juni 2005
  • Nu online
Ja, m'n patroon is [code]<font class="if"><hier tekst> &nbsp[/code] maar ik krijg het niet voor elkaar.


Hmm, je moet het even begrijpen, maar dan werkt het wel. Pattern:
code:
1
/<font class=\"if\">(.*?)&nbsp/s
2 matches were found:

Array
(
[0] => <font class="if">
Printer Tray Is
Empty. Add Paper
&nbsp
[1] =>
Printer Tray Is
Empty. Add Paper

)
:)

Ik test het overigens met http://www.switchplane.co...regular-expression-tester

[ Voor 83% gewijzigd door ThinkPad op 01-10-2012 20:16 ]


  • aaajeetee
  • Registratie: Augustus 2002
  • Laatst online: 29-11 11:21
Offtopic: ikzelf test vaak hier: http://regex.larsolavtorvik.com/
Is ietsje uitgebreider, maar zo zijn er ontzettend veel online regex testers.
Pagina: 1