#!/usr/bin/perl -w # # Stock Quote Module # # Currently actually a Yahoo Stock Quote Module; if I feel the urge I # may build a module tree instead. Based on previous Stock Exchange # efforts. # # Waider 07/06/2003 package Stock; use strict; use LWP::UserAgent; use HTML::TokeParser; use Date::Parse; my $CGISITE = 'http://finance.yahoo.com'; my $CGIROOT = $CGISITE . '/q?s='; my $ua; # XXX this only covers the ones I'm interested in my %currencies = ( 'L' => 'GBP', 'OL' => 'NOK', ); sub new { my $self = shift; my %options = @_; my $ua = new LWP::UserAgent; $ua->agent( "GeekToy/0.1 " . $ua->agent ); $ua->env_proxy(); my $obj = bless {}, $self; $obj->{'ua'} = $ua; $obj; } sub quote { my $self = shift; my ( $ticker, $exchange ) = ( $self->{'ticker'}, $self->{'exchange'}); my ( $date, $value, $currency ); $ticker ||= shift; $exchange ||= shift; $exchange ||= ""; die "No ticker specified" unless $ticker; if ( defined( $exchange ) and defined( $currencies{$exchange})) { $currency = $currencies{$exchange}; } else { $currency = "USD"; } $exchange = ".$exchange" if $exchange; my $url = $CGIROOT . $ticker . $exchange; $ENV{DEBUG} and print STDERR "fetching $url...\n"; grabpage: my $req = new HTTP::Request GET => $url; my $res = $self->{ua}->request( $req ); if ( $res->is_success ) { my $content = $res->content; if ( $content =~ /is no longer valid. It has changed to get_tag ) { # last if $p->get_trimmed_text eq "$ticker$exchange"; # 2003 09 05 if ( $p->get_trimmed_text eq "Last Trade:" ) { $foundit = 1; last; } } die "Failed to locate sentinel" unless $foundit; # value $p->get_tag( "b" ); $value = $p->get_trimmed_text( "/b" ); print STDERR "price: $currency $value\n" if $ENV{DEBUG}; $p->get_tag( "tr" ); $p->get_tag( "th", "td" ); # Trade Time: if (( my $caption = $p->get_trimmed_text ) ne "Trade Time:" ) { if ( $ENV{DEBUG} and open( DUMP, ">$ticker.$exchange.html" )) { print DUMP $content; } die "Page format ($url) changed, found $caption\nStopped"; } # date $p->get_tag( "td" ); $date = $p->get_trimmed_text; # unix-time the date my $udate = str2time( $date ); $udate ||= time; # if it's just a day spec then tweak it if ( $date =~ /jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/i ) { $udate += 60 * 60 * 24; } $date = $udate; } else { # HTML retrieve failed return; } return { 'date' => $date, 'value' => $value, 'currency' => $currency }; } 1;