Last active
December 19, 2015 02:38
-
-
Save syxanash/5884037 to your computer and use it in GitHub Desktop.
Google Finance client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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>(.*?) </h3>}i ) { | |
$company_name_parsed = $1; | |
print "\n", $company_name_parsed, ' '; | |
} | |
print $1, "\n\n" | |
if ( $lwp_content =~ m{</h3>(.*?) }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/ -/-/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 <[email protected]> | |
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