#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use Getopt::Long;
use File::Slurp;
use Term::ANSIColor;
use Env;
my $script_version = '0.3.4';
# 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.
# $company_description_parsed, is used when the option --info is called;
# It will contain all the information of the company.
my $company_name = '';
my $company_name_parsed = '';
my $company_description_parsed = '';
# $price_to_color, will be used in the sub function color_price() at the
# line 342, to color the name of the stock market quotes (in order to
# make it more readable data visualization). $file_content will be used
# instead, to contain the content of the file dot brk saved.
my $price_to_color = '';
my $file_content = '';
# The following group of scalars belong, to the function GetOptions().
# Each of them is used for the parameter which will be passed from
# command line.
my $parameter_show_info;
my $parameter_delete_item;
my $parameter_save_item;
my $parameter_read_item;
my $parameter_cleans_folder;
my $parameter_help;
# LWP::UserAgent scalars, which will compose the requests and the
# responses. At the end the $lwp_content will contain the page content.
my ( $lwp_useragent, $lwp_response, $lwp_content ) = ( '', '', '' );
# The following scalars, will be used to record the precise time when
# the stock quotes are saved in the database.
my $log_minutes = (localtime)[1];
my $log_hours = (localtime)[2];
my $log_day = (localtime)[3];
my $log_month = (localtime)[4];
my $log_year = 1900 + (localtime)[5];
# $price_id and $price_ch, will contain the information to show
# if the currency is in decline or is on the rise.
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 = (
'Range
(.*?)',
'52 week
(.*?)',
'Open
(.*?)',
'Vol / Avg.
(.*?)',
'Mkt cap
(.*?)',
'P/E
(.*?)',
'Div/yield
(.*?)',
'EPS
(.*?)',
'Shares
(.*?)',
'Beta
(.*?)',
'Inst. own
(.*?)',
'(.*?)
<',
);
# 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' => \$parameter_help,
'info' => \$parameter_show_info,
'remove' => \$parameter_delete_item,
'read' => \$parameter_read_item,
'save' => \$parameter_save_item,
'clear' => \$parameter_cleans_folder,
);
if ( defined($parameter_help) ) {
print color('green'), q {
Brokyplo }, color('reset'), $script_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 ( defined($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 = <> );
} 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 ( defined($parameter_read_item) );
remove_database($company_name)
if ( defined($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;
# 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">
(.*?)
}i ) {
$company_name_parsed = $1;
print "\n", $company_name_parsed, ' ';
}
print $1, "\n\n"
if ( $lwp_content =~ m{(.*?) }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 ( defined($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{}i );
$price_ch = $1
if ( $lwp_content =~ m{
print 'Price: ', $1, ' '
if ( $lwp_content =~ m{(.*?)}i );
print color_price( $1, $price_ch ), ' '
if ( $lwp_content =~ m{(.*?)}i );
print color_price( $1, $price_ch ), "\n\n"
if ( $lwp_content =~ m{(.*?)}i );
# Checks if the user wants to save the statistics in the database. The
# statistics files will be saved in dot brk.
if ( defined($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: ', $script_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/\*/\*/g
if ( $lwp_content =~ m{\*}i );
$lwp_content =~ s/ -/-/g;
for my $index ( 0 .. 10 ) {
if ( $lwp_content =~ m{$regular_expression_values[$index]}i ) {
defined($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 ( defined($parameter_save_item) ) {
print 'Stock quotes for ', color('blue'), $company_name_parsed,
color('reset'), ' successfully saved!', "\n\n"
if ( -e $main_folder . $company_name . '.brk' );
close $FILEHANDLE;
}
# Various sub functions
sub show_info {
$company_description_parsed = shift;
print $company_description_parsed, "\n\n";
exit;
}
sub remove_database {
$company_name = shift;
if ( -e $main_folder . $company_name . '.brk' ) {
unlink( $main_folder . $company_name . '.brk' );
print "\n", color('blue'), $company_name, 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 {
$company_name = shift;
if ( -e $main_folder . $company_name . '.brk' ) {
print read_file( $main_folder . $company_name . '.brk' ), "\n";
exit;
}
else {
die "\n", color('red'), 'The company doesn\'t exists in the database!',
color('reset'), "\n\n";
}
}
sub color_price {
$price_to_color = shift;
$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 EXAMPLES
Please enter the company name: Google
Google Inc. (Public, NASDAQ:GOOG)
Price: 600.62 -8.94 (-1.47%)
Stock quotes for Google Inc. successfully saved!
=head1 DESCRIPTION
Thanks to Google Finance, (www.google.com/finance), Brokyplo, can parse
some of the information of a company for example the stock quotes, the
currency and something else, and save it on a flat database. This script
works without any graphic interface, but only from a command line,
perfect for minimal desktop environments. If you want, you can save
something in the main folder, you can also remove these files saved as
dot brk, or read them simply from the command line with the
relative ARGV options.
=head1 SEE ALSO
http://www.google.com/finance
Env ~ http://search.cpan.org/~rjbs/perl-5.12.3/lib/Env.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
See the FAQ about Term modules at http://perldoc.perl.org/perlfaq8.html
=head1 COPYRIGHT
Copyright (C) 2010 by sysxash
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
sysxash with his mind -
=head1 THANKS
Thanks to perl.it irc channel @ irc.freenode.net
=cut