Skip to content

Instantly share code, notes, and snippets.

@syxanash
Last active December 19, 2015 02:38
Show Gist options
  • Save syxanash/5884037 to your computer and use it in GitHub Desktop.
Save syxanash/5884037 to your computer and use it in GitHub Desktop.
Google Finance client
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use Getopt::Long;
use File::Slurp;
use Term::ANSIColor;
use Env;
use vars qw($VERSION);
my $VERSION = '0.5.1';
# Set the main folder which contains all the saved data.
my $main_folder = "$HOME/.brokyplo/";
# This variable will contain the name of the company, for example
# Google Inc, Apple Inc, etc. $company_name_parsed will contain
# instead the full name of the company, parsed by a regexp.
my $company_name = '';
my $company_name_parsed = '';
# $file_content will be used
# instead, to contain the content of the file dot brk saved.
my $file_content = '';
my %argv_parameter = (
show_info => '',
delete_item => '',
save_item => '',
read_item => '',
cleans_folder => '',
show_help => '',
);
my ( $lwp_useragent, $lwp_response, $lwp_content ) = ( '', '', '' );
# The following hash will be used to record the exact time
# when stock quotes are saved in the database.
my %log = (
minutes => (localtime)[1],
hours => (localtime)[2],
day => (localtime)[3],
month => (localtime)[4],
year => 1900 + (localtime)[5],
);
# $price_id and $price_ch, will contain the information to show
# if the currency going down or up.
my ( $price_id, $price_ch ) = ( '', '' );
my $FILEHANDLE;
my $DIRHANDLE;
# This vector will be used to show all the information on the
# stock quotes, during the final iteration.
my @regular_expression_keys = (
'Range', '52 week', 'Open', 'Vol / Avg.',
'Mkt cap', 'P/E', 'Div/yield', 'EPS',
'Shares', 'Beta', 'Inst. own',
);
# @regular_expression_values, will contain the regexp to parse in the
# final iteration except the value eleven.
my @regular_expression_values = (
'data-snapfield="range">Range</td><td class="val">(.*?)</td>',
'data-snapfield="range_52week">52 week</td><td class="val">(.*?)</td>',
'data-snapfield="open">Open</td><td class="val">(.*?)</td>',
'data-snapfield="vol_and_avg">Vol / Avg.</td><td class="val">(.*?)</td>',
'data-snapfield="market_cap">Mkt cap</td><td class="val">(.*?)</td>',
'data-snapfield="pe_ratio">P/E</td><td class="val">(.*?)</td>',
'data-snapfield="latest_dividend-dividend_yield">Div/yield</td><td class="val">(.*?)</td>',
'data-snapfield="eps">EPS</td><td class="val">(.*?)</td>',
'data-snapfield="shares">Shares</td><td class="val">(.*?)</td>',
'data-snapfield="beta">Beta</td><td class="val">(.*?)</td>',
'data-snapfield="inst_own">Inst. own</td><td class="val">(.*?)</td>',
'<div class=companySummary>(.*?)<',
);
# Creates the main directory which will contain all the file dot brk.
# The file dot brk will contain expecially the stock quotes info
# existing in the @regular_expression_keys and catched by
# @regular_expression_values.
mkdir "$HOME/.brokyplo" unless ( -d $main_folder );
GetOptions(
'help' => \$argv_parameter{show_help},
'info' => \$argv_parameter{show_info},
'remove' => \$argv_parameter{delete_item},
'read' => \$argv_parameter{read_item},
'save' => \$argv_parameter{save_item},
'clear' => \$argv_parameter{cleans_folder},
);
if ( $argv_parameter{show_help} ) {
print color('green'), q {
Brokyplo }, color('reset'), $VERSION, q {
Usage: perl }, $0, q { [--options]
--info: show information about a company;
--save: save the reasults in the main folder;
--read: read a company saved in the past;
--remove: remove a specific company from the database;
--clear: clear the main directory which contains the stock quotes;
--help: show this help.
SEE THE PERLDOC (perldoc }, $0, q {) FOR MORE INFORMATION
};
exit;
}
if ( $argv_parameter{cleans_folder} ) {
if ( -d $main_folder ) {
opendir $DIRHANDLE, $main_folder
or die "Can't open the directory: $!\n";
while ( glob( $main_folder . '*' ) ) {
$FILEHANDLE = glob( $main_folder . '*' );
unlink $FILEHANDLE;
}
close $DIRHANDLE;
die "\n", color('green'), 'Stock quotes successfully removed!',
color('reset'), "\n\n";
}
else {
die "\n", color('red'), 'Main directory doesn\'t exists!',
color('reset'), "\n\n";
}
}
# Asks the company name via INPUT and makes lowercase
# characters in input.
do {
print q { , ,
)\\___/(
\{(@)v(@)\}
\{|~~~|\}
\{|~~~|\}
\{/^^^\\\}
=======`m-m`====\
Please enter the company name: };
chomp( $company_name = <STDIN> );
} while ( $company_name eq '' );
$company_name = lc($company_name);
# Checks if the user wants to read or remove something from the database
read_database($company_name)
if ( $argv_parameter{read_item} );
remove_database($company_name)
if ( $argv_parameter{delete_item} );
$lwp_useragent = LWP::UserAgent->new;
$lwp_useragent->agent('Mozilla/5.0');
$lwp_response = $lwp_useragent->get( 'http://www.google.com/finance?q=' . $company_name );
die "\n", color('red'), 'Error during extablishing the connection with the remote host...', color('reset'), "\n\n"
unless ( $lwp_response->is_success );
$lwp_content = $lwp_response->content;
# Removing the carriage return from the html
$lwp_content =~ s/\n//g;
# Checks if company exists in the Google Finance database
die "\n", color('red'), 'Company name doesn\'t exists', color('reset'),
', please be more precise...', "\n\n"
if ( $lwp_content =~ m{produced no matches}i
or $lwp_content =~ m{Results 1}i );
# Starts parsing the company name and prints the results.
if ( $lwp_content =~ m{class="g-unit g-first"><h3>(.*?)&nbsp;&nbsp;</h3>}i ) {
$company_name_parsed = $1;
print "\n", $company_name_parsed, ' ';
}
print $1, "\n\n"
if ( $lwp_content =~ m{</h3>(.*?)&nbsp;&nbsp;}i );
# Checks if the user just wants to view the information about the company
# if true, is called the sub function show_info() on the line 299.
if ( $argv_parameter{show_info} ) {
show_info($1)
if ( $lwp_content =~ m{$regular_expression_values[11]}i );
}
# Starts parsing the price and the currency. Well, honestly I don't like
# so much this kind of solution... but I had to do it! If you have any
# advices about this block of code let me know!
$price_id = $1
if ( $lwp_content =~ m{<span id="ref_(.*?)_l">}i );
$price_ch = $1
if ( $lwp_content =~ m{<span class="ch bld"><span class="(.*?)" id}i );
print 'Price: ', $1, ' '
if ( $lwp_content =~ m{<span id="ref_$price_id\_l">(.*?)</span>}i );
print color_price( $1, $price_ch ), ' '
if ( $lwp_content =~
m{<span class="ch bld"><span class="$price_ch\" id="ref_$price_id\_c">(.*?)</span>}i
);
print color_price( $1, $price_ch ), "\n\n"
if ( $lwp_content =~
m{<span class="$price_ch\" id="ref_$price_id\_cp">(.*?)</span>}i );
# Checks if the user wants to save the statistics in the database. The
# statistics files will be saved in dot brk.
if ( $argv_parameter{save_item} ) {
open $FILEHANDLE, '>>', $main_folder . $company_name . '.brk'
or die "Can't open file handle: $!\n";
# Checks if the file doesn't contains the banner, if true, writes the
# banner with the program version and the full company name.
$file_content = read_file( $main_folder . $company_name . '.brk' );
print {$FILEHANDLE} "\n", 'Brokyplo version: ', $VERSION, "\n\n",
'Company name: ', $company_name_parsed, "\n"
if ( $file_content !~ m{Brokyplo version:}i );
print {$FILEHANDLE} "\n", '---', $log{hours}, ':', $log{minutes}, '---',
$log{month}, '/', $log{day}, '/', $log{year}, '---', "\n\n";
}
# Parse the rest of the body of the Google Finance page and shows the
# various information about the stock quotes.
$lwp_content =~ s/<span class=dis>\*/\*/g
if ( $lwp_content =~ m{<span class=dis>\*}i );
$lwp_content =~ s/&nbsp;&nbsp;&nbsp;&nbsp;-/-/g;
for my $index ( 0 .. 10 ) {
if ( $lwp_content =~ m{$regular_expression_values[$index]}i ) {
$argv_parameter{save_item}
? print {$FILEHANDLE} $regular_expression_keys[$index], ': ', $1, "\n"
: print $regular_expression_keys[$index], ': ', color('blue'), $1, color('reset'), "\n";
}
}
# Makes the final check, to control if the file was successfully saved,
# and closes the file-handle.
if ( $argv_parameter{save_item} ) {
close $FILEHANDLE;
print 'Stock quotes for ', color('blue'), $company_name_parsed, color('reset'), ' successfully saved!', "\n\n"
if ( -e $main_folder . $company_name . '.brk' );
}
# Various sub functions
sub show_info {
my $company_description_parsed = shift;
print $company_description_parsed, "\n\n";
exit;
}
sub remove_database {
my $company = shift;
if ( -e $main_folder . $company . '.brk' ) {
unlink( $main_folder . $company . '.brk' );
print "\n", color('blue'), $company, color('reset'),
color('green'), '.brk, successfully removed from database!',
color('reset'), "\n\n";
exit;
}
else {
die "\n", color('red'), 'The company doesn\'t exists in the database!',
color('reset'), "\n\n";
}
}
sub read_database {
my $company = shift;
if ( -e $main_folder . $company . '.brk' ) {
print read_file( $main_folder . $company . '.brk' ), "\n";
exit;
}
else {
die "\n", color('red'), 'The company doesn\'t exists in the database!',
color('reset'), "\n\n";
}
}
sub color_price {
my $price_to_color = shift;
my $price_ch = shift;
$price_ch eq 'chg'
? return color('green'), $price_to_color, color('reset')
: return color('red'), $price_to_color, color('reset');
}
__END__
=head1 NAME
Brokyplo
=head1 SYNOPSIS
perl brokyplo.pl [--options]
--info: show information about a company;
--save: save the reasults in the main folder;
--read: read a company saved in the past;
--remove: remove a specific company from the database;
--clear: clear the main directory which contains the stock quotes;
--help: show this help.
=head1 DESCRIPTION
Brokyplo is a script which is able to parse information
from the web service Google Finance. This script works
directly from command line and allows you to save information
about companies and stock quotes on a flat file database.
=head1 SEE ALSO
http://www.google.com/finance
See the FAQ about Term modules at http://perldoc.perl.org/perlfaq8.html
=head1 DEPENDENCIES
vars ~ http://search.cpan.org/~lbrocard/perl-5.12.4/lib/vars.pm
Getopt::Long ~ http://search.cpan.org/~enrys/POD2-IT-Getopt-Long/lib/POD2/IT/Getopt/Long.pm
LWP::UserAgent ~ http://search.cpan.org/~gaas/libwww-perl-5.837/lib/LWP/UserAgent.pm
File::Slurp ~ http://search.cpan.org/~drolsky/File-Slurp-9999.13/lib/File/Slurp.pm
Env ~ http://search.cpan.org/~rjbs/perl-5.12.3/lib/Env.pm
=head1 LICENSE AND COPYRIGHT
Copyright (C) 2010 by syxanash <syxanash@cpan.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
On Debian systems, the complete text of the GNU General Public License
can be found in /usr/share/common-licenses/GPL-3.
=head1 AUTHOR
@syxanash
=cut
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment