PDA

View Full Version : Polling the Grand Exchange in PHP?



jimthesoundman
02-13-2010, 01:33 AM
Anyone know how to look up Grand Exchange prices using PHP?

I'm trying to figure it out, but I'm not having much success.

Step one is figuring out what the item number is.

I don't know whether it's possible to do that dynamically or whether I'll have to build a database with all the item names and item numbers.

Next step would be pulling up the appropriate page at services.runescape.com and finding the price.

I was just going to adapt this function from SCAR to PHP somehow:


Function GetIDPrice(ItemID: Integer): Integer;
Var
s: String;
Begin
s := getpage('http://itemdb-rs.runescape.com/viewitem.ws?obj=' + IntToStr(ItemID));
s := between('Market price:</b>', '</span>', s);
s := getnumbers(s);
Result := StrToInt(s);
End;

Anyone have any suggestions or tips for me?

Thanks in advance,

JIM

Sex
02-13-2010, 02:10 AM
Try to use the CURL library for php it is much faster than file_get_contents.

jimthesoundman
02-13-2010, 02:39 AM
Can you clue me in as to how it would work or point me towards a tutorial? I've never used cURL before.

Edit: Oh, after looking at your answer again... were you thinking I was gonna put all those various items in a file? I was planning on using a MySQL database. I don't think there will be any lag or speed issues.

Thanks,

JIM

Sex
02-13-2010, 05:50 AM
No. I meant using it to get the data of the page you are querying..

silentwolf
02-15-2010, 12:58 PM
<?php

$page = file_get_contents('http://itemdb-rs.runescape.com/viewitem.ws?obj='.$_GET[id]);

$search = 'Market price:</b>';
$start = strpos($page,$search)+strlen($search);
$search = '</span>';
$end = strpos($page,$search,$start);
$result = substr($page,$start,$end-$start);

echo $result;
?>


My hacky PHP. Not sure if I get the order some some function variables right, but hopefully you get the idea :)

Frement
02-15-2010, 01:06 PM
<?php

function str_between( $string, $start, $end ){
$string = " " . $string;
$ini = strpos( $string, $start );
if ( $ini == 0 ) return "";
$ini += strlen( $start );
$len = strpos( $string, $end, $ini ) - $ini;
return substr( $string, $ini, $len );
}

?>

Theres a simple function to find string between 2 strings.

Also take a look at strip_tags();

E: Made an example: http://www.frement.net/srl/ge.php

Boreas
02-15-2010, 02:42 PM
This should get you an INI with names/IDs, unless they have changed something. Shouldn't be a problem to modify it to XML or something if PHP doesn't like INI.
program New;
var
Page,ObjNum,ObjName,ObjPrice:string;
iter,Letter,PLP1,PLP2,ObjNum1,PageLimit,ObjNum2,Ob jName2,ObjPrice2,ObjPrice1,time,t,t1,PageNumber:in teger;
ObjPriceN:extended;
PageLimitSet:boolean;

begin
time:=getsystemtime;
Letter:=1;
repeat
PageNumber:=1;
repeat
if chr(64+Letter) = 'Q' then
begin
Letter:=Letter+1;
break;
end;
Page := GetPage('http://itemdb-rs.runescape.com/results.ws?query=&sup=Initial%20Letter&cat='+chr(Letter+64)+'&sub=All&page='+inttostr(PageNumber)+'&vis=1&order=1&sortby=name&price=&members=');
if not PageLimitSet then
begin
//writeln('Setting PageLimit');
PLP1:=Pos('<td class="navright">',Page);
PLP2:=LastPosEx('ers=">',Page,PLP1);
if PLP2=-1 then
begin
PageLimit:=1;
PageLimitSet:=true;
end;
if PageLimitSet=false then
begin
PLP1:=PosEx('</a>',Page,PLP2);
PageLimit:=strtoint(Copy(Page,PLP2+6,PLP1-PLP2-6));
end;
PageLimitSet:=true;
// writeln(chr(letter+64)+' '+inttostr(pagelimit));
end;
t:=Pos('Change Today',Page);
repeat
ObjNum1:=PosEx('em.ws?obj=',Page,t);
if ObjNum1=-1 then
begin
Page:='';
//writeln('Last Item '+inttostr(PageNumber)+' '+inttostr(pagelimit));
break;
end;
ObjNum2:=PosEx('">',Page,ObjNum1);
ObjNum:=Copy(Page,ObjNum1+10,ObjNum2-ObjNum1-10);
ObjName2:=PosEx('</a',Page,ObjNum2);
ObjName:=Copy(Page,ObjNum2+3,ObjName2-ObjNum2-3);
ObjPrice1:=PosEx('<td>',Page,ObjName2);
ObjPrice2:=PosEx('</td>',Page,ObjPrice1);
ObjPrice:=Copy(Page,ObjPrice1+4,ObjPrice2-ObjPrice1-4);
if pos('k',ObjPrice)>0 then
begin
ObjPriceN:=StrToFloat(TrimLetters(ObjPrice));
ObjPriceN:=ObjPriceN*1000;
end;
if pos('m',ObjPrice)>0 then
begin
ObjPriceN:=StrToFloat(TrimLetters(ObjPrice));
ObjPriceN:=ObjPriceN*1000000;
end;
ObjPrice:=TrimOthers(ObjPrice);
if (pos('k',ObjPrice)=0)and(pos('m',ObjPrice)=0) then
ObjPriceN := strtofloat(ObjPrice);

//writeln(ObjNum+' '+ObjName+' '+floattostr(ObjPriceN));

WriteINI('NumberToName',ObjNum,ObjName,AppPath+'GE .ini');
WriteINI('NameToNumber',ObjName,ObjNum,AppPath+'GE .ini');
WriteINI('Search',inttostr(t1)+'U',ObjNum,AppPath+ 'GE.ini');
WriteINI('Search',inttostr(t1)+'A',ObjName,AppPath +'GE.ini');

//Dump to file, send to database, etc
t1:=t1+1;
t:=ObjName2;
until isfkeydown(11);
PageNumber:=PageNumber+1;
if PageNumber>PageLimit then
begin
PageLimitSet:=false;
Letter:=Letter+1;
break;
end;
until isfkeydown(11);
if Letter>26 then
break;
until isfkeydown(11);
writeln(inttostr(t1)+' items in '+inttostr(getsystemtime-time)+'ms');

end.


usable with
program New;

function NameToNumber(Name:string):integer;
begin
result:=strtoint(ReadINI('NameToNumber',Name,AppPa th+'GE.ini'));
end;

function NumberToName(Num:integer):string;
begin
result:=ReadINI('NumberToName',inttostr(Num),AppPa th+'GE.ini');
end;

function Search(term:string):integer;
var tmpstr:string;
count,count2:integer;
MyArr:array of integer;
begin
writeln('Press F11 when there are enough results');
writeln('Press F10 to start');
repeat
wait(20);
until isfkeydown(10);
repeat
tmpstr:=ReadIni('Search', inttostr(count)+'A',AppPath+'GE.ini');
if pos(lowercase(term),lowercase(tmpstr))>0 then
begin
writeln(inttostr(count2)+' '+tmpstr);
setarraylength(MyArr,count2+1);
MyArr[count2]:=strtoint(ReadIni('Search', inttostr(count)+'U',AppPath+'GE.ini'));
count2:=count2+1;
end;
count:=count+1;
until ((isfkeydown(11)) or (count=3203));
writeln('Press F12 when you know which number');
repeat
wait(20);
until isfkeydown(12);
result:=MyArr[strtoint(ReadLn('Which number?'))];
end;

function CurrentPrice(ObjNum:integer):integer;
var tmpstr,Page:string;
Pos1,Pos2:integer;
tmpfloat:extended;
begin
Page := GetPage('http://itemdb-rs.runescape.com/viewitem.ws?obj='+inttostr(ObjNum));
Pos1:=Pos('>Market price:</b> ',Page);
Pos2:=PosEx('</span>',Page,Pos1);
tmpstr:=Copy(Page,Pos1+19,Pos2-Pos1-20);
if pos('k',tmpstr)>0 then
begin
tmpfloat:=StrToFloat(TrimLetters(tmpstr));
result:=round(tmpfloat*1000);
end;
if pos('m',tmpstr)>0 then
begin
tmpfloat:=StrToFloat(TrimLetters(tmpstr));
result:=round(tmpfloat*1000000);
end;
tmpstr:=TrimOthers(tmpstr);
if (pos('k',tmpstr)=0)and(pos('m',tmpstr)=0) then
result := strtoint(tmpstr);
Page:='';
end;

begin

writeln(NumberToName(1059));
writeln(inttostr(NameToNumber('Leather gloves')));
//writeln(NumberToName(Search('gold')));
writeln(inttostr(CurrentPrice(8445)));
writeln(inttostr(CurrentPrice(Search(Readln('searc h for an item')))));

end.