Last active
January 10, 2023 15:00
-
-
Save jaggzh/f004a9917c2cb50ec2e10d24ed925dcd to your computer and use it in GitHub Desktop.
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 | |
# gist url: https://gist.github.com/jaggzh/f004a9917c2cb50ec2e10d24ed925dcd | |
# Processes CSV output from an amazon-buddy command | |
# About: | |
# Originally I wrote this for cost/pill for supplements. | |
# In its present state it's modified for finding syringes, | |
# evaluating with the regexes for "2 pack" "5ct" etc. | |
# Setup & Requirements: | |
# bansi.pm: https://gist.github.com/jaggzh/7b22252263719757e17ca710ac091110 | |
# amazon-buddy: https://www.npmjs.com/package/amazon-buddy | |
# | |
# * Note: You'll need to put bansi.pm somewhere where perl will find it. | |
# Like: $ mkdir ~/lib/perl && cd ~/lib/perl | |
# $ curl https://gist.githubusercontent.com/jaggzh/7b22252263719757e17ca710ac091110/raw/1876123228de37a1cf2f2628c35d0ed32a888c31/bansi.pm -O | |
# Then add that directory to your PERL5LIB env var, probably by adding | |
# a line to your shell's profile script: | |
# $ export PERL5LIB="${PERL5LIB:+$PERL5LIB:}/home/jaggz/lib/perl" | |
# Examples: | |
# 1. A simple search and processing: | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy-cost-per-syringe.pl {output_csv_from_above_command} 2>&1 | less -R | |
# 2. Join some searches (the sort|uniq isn't really necessary, | |
# since we remove duplicates based on amazon-id ("asin"). | |
# $ mkdir amazon-syringes && cd amazon-syringes | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy -n 300 products -k '250ml syringes' | |
# $ cat products*.csv | sort | uniq > uniq.csv | |
# $ amazon-buddy-cost-per-syringe.pl {uniq.csv} 2>&1 | less -R | |
use strict; use warnings; use 5.24.1; | |
use Text::CSV qw(csv); | |
use bansi; | |
my $aoh = csv( | |
in => $ARGV[0], | |
headers => "auto"); # as array of hash | |
$|=1; | |
binmode *STDOUT, ':encoding(UTF-8)'; | |
say join(' ', keys %{$aoh->[0]}); | |
#say $aoh->{title}[0]; | |
#say $aoh->[1]->{title}; | |
my @bycost; | |
my %found_already; # Uses the "asin" field | |
sub show_item { # idx, itemref, {flags {show=>0}} | |
my $i = shift; | |
my $item = shift; | |
my $flags = shift; | |
my $show = $flags->{show} // 1; | |
my $tit = $item->{title}; | |
my $url = $item->{url}; | |
my $price = $item->{"price.current_price"}; | |
my $asin = $item->{"asin"}; | |
my ($mg) = ($tit =~ /(\d+)\s*mg\b/); | |
if (!defined $mg) { | |
#say "[$i] $yel\[Bad mg]$rst $tit"; | |
} else { | |
#say "[${mg}mg] $tit"; | |
} | |
my ($packs, $cnt, $ml, $mlstr); | |
($packs) = ($tit =~ /(\d+)(?:\s*|-)(?:pack|packs|set|sets|pcs)\b/i) if !defined $packs; | |
($packs) = ($tit =~ /(?:pack|set|box) of (\d+)/i) if !defined $packs; | |
($ml) = ($tit =~ /((\d+\.)?\d+)\s*(ml|cc)\b/i) if !defined $ml; | |
($cnt) = ($tit =~ /(\d+)\s*(Vegetarian Capsules|Capsules|VegCaps)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*(:?ct|count)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*ea\b/i) if !defined $cnt; | |
# $mg = '?mg' if !defined $mg; | |
# $cnt = '?cnt' if !defined $cnt; | |
my $packstr = defined $packs ? " x $packs" : ""; | |
my $lowml=0; | |
if (defined $ml && $ml > 1 && $ml < 150) { $lowml=1; } | |
if (defined $cnt && defined $mg) { | |
say "1 [$i] [$whi${mg}mg$rst x $bcya${cnt}$packstr$rst] $bmag$tit $bbla$url$rst" if $show; | |
} elsif (defined $mg) { # only mg | |
say "2 [$i] [$cya${mg}mg$rst x ?$packstr] $tit $bbla$url$rst" if $show; | |
} elsif (defined $cnt) { # only cnt | |
say "3 [$i] ${red}[?mg x $bcya$cnt$packstr$rst] $tit $bbla$url$rst" if $show; | |
} else { | |
$packs = 1 if !defined $packs; | |
$price = 0 if !defined $price; | |
$cnt = 1 if !defined $cnt; | |
if (defined $ml && $ml > 0 && $ml < 150) { | |
say "${bbla}x [$i] ${packs}ct ${ml}ml $tit $bbla$url$rst" if $show; | |
} else { | |
if (!defined $ml) { $mlstr = "$red?ml$rst"; $ml=1; } | |
else { $mlstr = "${whi}${ml}ml"; } | |
# say $i; | |
# say $price/$packs; | |
# say "$price"; | |
# say "${packs}ct"; | |
# say "${ml}"; | |
# say "Tit: $tit"; | |
# say "URL: $url"; | |
printf "4 [%3d]$rst %5.2f %6s ${bbla}%5s$rst %6s ${yel}%s $bbla%s$rst\n", | |
# 1 2 3 4 5 6 7 | |
#1 2 3 4 5 6 7 | |
$i, $price/$packs, "$price", "${packs}ct", "$mlstr", $tit, $url | |
if $show; | |
my $keep = 0; | |
if ($tit !~ /bottle/i && $ml >= 200) { $keep = 1; } | |
if ($ml >= 1) { $keep = 1; } | |
if ($keep) { | |
if (!exists $found_already{$asin}) { | |
$found_already{$asin}++; | |
push @bycost, { | |
cost=>$price/$packs, | |
item=>$item, | |
}; | |
} | |
} | |
} | |
} | |
} | |
for my $i (1 .. $#{$aoh}) { | |
my $item = $aoh->[$i]; | |
show_item($i, $item, { show => 0 }); | |
} | |
@bycost = sort { $a->{cost} <=> $b->{cost} } @bycost; | |
for my $i (1 .. $#bycost) { | |
show_item($i, $bycost[$i]->{item}); | |
} | |
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 | |
# gist url: https://gist.github.com/jaggzh/f004a9917c2cb50ec2e10d24ed925dcd | |
# Processes CSV output from an amazon-buddy command | |
# About: | |
# Originally I wrote this for cost/pill for supplements. | |
# In its present state it's modified for finding syringes, | |
# evaluating with the regexes for "2 pack" "5ct" etc. | |
# Setup & Requirements: | |
# bansi.pm: https://gist.github.com/jaggzh/7b22252263719757e17ca710ac091110 | |
# amazon-buddy: https://www.npmjs.com/package/amazon-buddy | |
# | |
# * Note: You'll need to put bansi.pm somewhere where perl will find it. | |
# Like: $ mkdir ~/lib/perl && cd ~/lib/perl | |
# $ curl https://gist.githubusercontent.com/jaggzh/7b22252263719757e17ca710ac091110/raw/1876123228de37a1cf2f2628c35d0ed32a888c31/bansi.pm -O | |
# Then add that directory to your PERL5LIB env var, probably by adding | |
# a line to your shell's profile script: | |
# $ export PERL5LIB="${PERL5LIB:+$PERL5LIB:}/home/jaggz/lib/perl" | |
# Examples: | |
# 1. A simple search and processing: | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy-cost-per-syringe.pl {output_csv_from_above_command} 2>&1 | less -R | |
# 2. Join some searches (the sort|uniq isn't really necessary, | |
# since we remove duplicates based on amazon-id ("asin"). | |
# $ mkdir amazon-syringes && cd amazon-syringes | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy -n 300 products -k '250ml syringes' | |
# $ cat products*.csv | sort | uniq > uniq.csv | |
# $ amazon-buddy-cost-per-syringe.pl {uniq.csv} 2>&1 | less -R | |
# 3. A search showing the cost per 10, and --pieces to not do ml, mg, etc. | |
# $ amazon-buddy-cost-per-syringe.pl -per=10 --pieces products.csv | |
use strict; use warnings; use 5.24.1; | |
use Text::CSV qw(csv); | |
use bansi; | |
use Getopt::Long; | |
my $opts; | |
my @bycost; | |
my %found_already; # Uses the "asin" field | |
sub show_item { # idx, itemref, {flags {show=>0}} | |
my $i = shift; | |
my $item = shift; | |
my $flags = shift; | |
my $show = $flags->{show} // 1; | |
my $tit = $item->{title}; | |
my $url = $item->{url}; | |
my $price = $item->{"price.current_price"}; | |
my $asin = $item->{"asin"}; | |
my ($mg) = ($tit =~ /(\d+)\s*mg\b/); | |
if (!defined $mg) { | |
#say "[$i] $yel\[Bad mg]$rst $tit"; | |
} else { | |
#say "[${mg}mg] $tit"; | |
} | |
my ($packs, $cnt, $ml, $mlstr); | |
($packs) = ($tit =~ /(\d+)(?:\s*|-)(?:pack|packs|set|sets|pcs)\b/i) if !defined $packs; | |
($packs) = ($tit =~ /(?:pack|set|box) of (\d+)/i) if !defined $packs; | |
($ml) = ($tit =~ /((\d+\.)?\d+)\s*(ml|cc)\b/i) if !defined $ml; | |
($cnt) = ($tit =~ /(\d+)\s*(Vegetarian Capsules|Capsules|VegCaps)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*(:?ct|count)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*ea\b/i) if !defined $cnt; | |
# $mg = '?mg' if !defined $mg; | |
# $cnt = '?cnt' if !defined $cnt; | |
my $packstr = defined $packs ? " x $packs" : ""; | |
my $lowml=0; | |
if (defined $ml && $ml > 1 && $ml < 150) { $lowml=1; } | |
if (defined $cnt && defined $mg) { | |
say "1 [$i] [$whi${mg}mg$rst x $bcya${cnt}$packstr$rst] $bmag$tit $bbla$url$rst" if $show; | |
} elsif (defined $mg) { # only mg | |
say "2 [$i] [$cya${mg}mg$rst x ?$packstr] $tit $bbla$url$rst" if $show; | |
} elsif (defined $cnt) { # only cnt | |
say "3 [$i] ${red}[?mg x $bcya$cnt$packstr$rst] $tit $bbla$url$rst" if $show; | |
} else { | |
$packs = 1 if !defined $packs; | |
$price = 0 if !defined $price; | |
$cnt = 1 if !defined $cnt; | |
if (!defined $ml) { $mlstr = "$red?ml$rst "; $ml=1; } | |
else { $mlstr = "${whi}${ml}ml "; } | |
$mlstr = '' if $$opts{pieces}; | |
# say $i; | |
# say $price/$packs; | |
# say "$price" if $show; | |
# say "${packs}ct"; | |
# say "${ml}"; | |
# say "Tit: $tit"; | |
# say "URL: $url"; | |
printf "4 [%3d] $rst%5.2f %6s ${bbla}%5s$rst %6s ${yel}%s $bbla%s %s$rst\n", | |
# 1 2 4 5 6 7 8 9 | |
$i, # 1 | |
$$opts{per} * $price/$packs, # 2 | |
$price, # 4 | |
"${packs}ct", # 5 | |
"$mlstr", # 6 | |
$tit, # 7 | |
$asin, # 8 | |
$url # 9 | |
if $show; | |
my $keep = 1; | |
if ($$opts{mlmin} != $$opts{mlmax}) { | |
$keep = 0 if $ml < $$opts{mlmin}; | |
$keep = 0 if $ml >= $$opts{mlmax}; | |
} | |
$keep = 0 if exists $$opts{excludere} && $tit =~ /$$opts{excludere}/i; | |
if ($keep) { | |
if (!exists $found_already{$asin}) { | |
$found_already{$asin}++; | |
push @bycost, { | |
cost=>$price/$packs, | |
item=>$item, | |
}; | |
} | |
} | |
} | |
} | |
sub getopts { | |
my %opts; | |
$opts{verbose} = 0; | |
$opts{mlmin} = 0; | |
$opts{mlmax} = 0; | |
$opts{mgmin} = 0; | |
$opts{mgmax} = 0; | |
$opts{pieces} = 0; | |
$opts{per} = 1; | |
# $opts{infn} = "foo.dat"; | |
GetOptions(\%opts, | |
"verbose", | |
"mlmin=i", | |
"mlmax=i", | |
"per=i", | |
"pieces", | |
"excludere=s", # regex to exclude | |
#"length=i" => \$opts{length}, # numeric | |
# "i|file=s" => \$opts{infn}, # string | |
) or die("Error in command line arguments\n"); | |
return \%opts; | |
} | |
sub main { | |
$opts = getopts(); | |
my $aoh = csv( | |
in => $ARGV[0], | |
headers => "auto"); # as array of hash | |
$|=1; | |
binmode *STDOUT, ':encoding(UTF-8)'; | |
say join(' ', keys %{$aoh->[0]}); | |
#say $aoh->{title}[0]; | |
#say $aoh->[1]->{title}; | |
for my $i (1 .. $#{$aoh}) { | |
my $item = $aoh->[$i]; | |
show_item($i, $item, { show => 0 }); | |
} | |
@bycost = sort { $a->{cost} <=> $b->{cost} } @bycost; | |
say "${whi}Price per $$opts{per} count$rst" if $$opts{per} != 1; | |
for my $i (1 .. $#bycost) { | |
show_item($i, $bycost[$i]->{item}); | |
} | |
} | |
main(); |
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 | |
# gist url: https://gist.github.com/jaggzh/f004a9917c2cb50ec2e10d24ed925dcd | |
# Processes CSV output from an amazon-buddy command | |
# About: | |
# Originally I wrote this for cost/pill for supplements. | |
# In its present state it's modified for finding syringes, | |
# evaluating with the regexes for "2 pack" "5ct" etc. | |
# Setup & Requirements: | |
# bansi.pm: https://gist.github.com/jaggzh/7b22252263719757e17ca710ac091110 | |
# amazon-buddy: https://www.npmjs.com/package/amazon-buddy | |
# | |
# * Note: You'll need to put bansi.pm somewhere where perl will find it. | |
# Like: $ mkdir ~/lib/perl && cd ~/lib/perl | |
# $ curl https://gist.githubusercontent.com/jaggzh/7b22252263719757e17ca710ac091110/raw/1876123228de37a1cf2f2628c35d0ed32a888c31/bansi.pm -O | |
# Then add that directory to your PERL5LIB env var, probably by adding | |
# a line to your shell's profile script: | |
# $ export PERL5LIB="${PERL5LIB:+$PERL5LIB:}/home/jaggz/lib/perl" | |
# Examples: | |
# 1. A simple search and processing: | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy-cost-per-syringe.pl {output_csv_from_above_command} 2>&1 | less -R | |
# 2. Join some searches (the sort|uniq isn't really necessary, | |
# since we remove duplicates based on amazon-id ("asin"). | |
# $ mkdir amazon-syringes && cd amazon-syringes | |
# $ amazon-buddy -n 300 products -k '150ml syringes' | |
# $ amazon-buddy -n 300 products -k '250ml syringes' | |
# $ cat products*.csv | sort | uniq > uniq.csv | |
# $ amazon-buddy-cost-per-syringe.pl {uniq.csv} 2>&1 | less -R | |
# 3. A search showing the cost per 10, and --pieces to not do ml, mg, etc. | |
# $ amazon-buddy-cost-per-syringe.pl -per=10 --pieces products.csv | |
use strict; use warnings; use 5.24.1; | |
use Text::CSV qw(csv); | |
use bansi qw(:all); | |
use Getopt::Long; | |
my $opts; | |
my @opt_requirere; # This option (--requirere) can appear multiple times | |
my @opt_excludere; # This option (--requirere) can appear multiple times | |
my @bycost; | |
my %found_already; # Uses the "asin" field | |
my $verbose=0; | |
sub show_item { # idx, itemref, {flags {show=>0}} | |
my $i = shift; | |
my $item = shift; | |
my $flags = shift; | |
my $show = $flags->{show} // 1; | |
my $tit = $item->{title}; | |
my $prime = $item->{amazonPrime}; | |
my $url = $item->{url}; | |
my $price = $item->{"price.current_price"}; | |
my $asin = $item->{"asin"}; | |
my $length; | |
my ($mg) = ($tit =~ /(\d+)\s*mg\b/); | |
my $len_units = ''; | |
return if $$opts{prime} && $prime ne "true"; | |
say "AA ${whi}[$asin] $rst$tit" if $verbose > 1; | |
if (!defined $mg) { | |
#say "[$i] $yel\[Bad mg]$rst $tit"; | |
} else { | |
#say "[${mg}mg] $tit"; | |
} | |
my ($packs, $cnt, $ml, $mlstr, $weight); | |
my ($lbs, $grams, $kg); | |
if ($$opts{weight}) { | |
($lbs) = ($tit =~ /(\d+(\.\d+)?)\W*(?:lbs?)\b/i) if !defined $lbs; | |
# say "*weight* lbs=$lbs" if defined $lbs; | |
($lbs) = ($tit =~ /(\d+(\.\d+)?)\W*(?:pounds?)\b/i) if !defined $lbs; | |
if (!defined $lbs) { | |
($grams) = ($tit =~ /(\d+(\.\d+)?)\W*(?:g|gm|grams?)\b/i); | |
($kg) = ($tit =~ /(\d+(\.\d+)?)\W*kg\b/i); | |
if (defined $grams) { $lbs = $grams / 453.59; } | |
elsif (defined $kg) { $lbs = $kg * 2.2046; } | |
} | |
if (!defined $lbs) { | |
my ($ounces) = ($tit =~ /(\d+(\.\d+)?)\W*(?:oz|ounces?)\b/i); | |
$lbs = $ounces/16 if defined $ounces; | |
} | |
if (defined $lbs) { | |
$packs = $cnt = $lbs; | |
} else { | |
$packs = $cnt = 10000; | |
} | |
} | |
if ($$opts{pieces}) { | |
($packs) = ($tit =~ /(\d+)(?:\s*|-)(?:pack|packs|set|sets|pcs)\b/i) if !defined $packs; | |
($packs) = ($tit =~ /(?:pack|set|box) of (\d+)/i) if !defined $packs; | |
($packs) = ($tit =~ /(\d+)(?:\s*|-)(?:rolls?)\b/i) if !defined $packs; | |
($packs) = ($tit =~ /(\d+)(?:\s*|-)(?:pieces?)\b/i) if !defined $packs; | |
} | |
($ml) = ($tit =~ /((\d+\.)?\d+)\s*(ml|cc)\b/i) if !defined $ml; | |
if ($$opts{length}) { | |
if (!defined $length) { | |
($length, $len_units) = ($tit =~ /(\d+)\s*-?(feet|'|ft|foot)/i); | |
warn "$bred ?? FEET$rst" if $verbose > 1; | |
$len_units = 'feet'; | |
} | |
if (!defined $length) { | |
($length, $len_units) = ($tit =~ /(\d+)\s*-?(in|inch|inches|")/i); | |
warn "$bred ?? INCHES$rst" if $verbose > 1; | |
$len_units = 'inches'; | |
} | |
if (!defined $length) { | |
($length, $len_units) = ($tit =~ /\W(\d+)\s*(m|meters)\W/i); | |
warn "$bred ?? METERS$rst" if $verbose > 1; | |
$len_units = 'm'; | |
} | |
$length = .0001 if !defined $length;; | |
} | |
($cnt) = ($tit =~ /(\d+)\s*(Vegetarian Capsules|Capsules|VegCaps)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*(caps\b)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*(:?ct|count)/i) if !defined $cnt; | |
($cnt) = ($tit =~ /(\d+)\s*ea\b/i) if !defined $cnt; | |
# $mg = '?mg' if !defined $mg; | |
# $cnt = '?cnt' if !defined $cnt; | |
my $packstr = defined $packs ? " x $packs" : ""; | |
if ($$opts{length}) { | |
if (!defined $length) { $length=1; $len_units='feet'; } | |
else { | |
if ($len_units eq 'm') { | |
$length *= 3.2808399; | |
$len_units = 'feet'; | |
} elsif ($len_units eq '') { | |
$len_units = 'feet'; | |
$length = 0.0001; | |
} elsif ($len_units eq 'inches') { | |
$len_units = 'feet'; | |
$length /= 12; | |
} elsif ($len_units ne 'feet') { | |
die "Unknown length unit (units:$len_units, length:$length): $asin $url '$bcya$tit$rst'"; | |
} | |
} | |
$packs = $length; | |
#say "${bmag}Using packs as units of length ($whi$len_units$bmag)$rst"; | |
} | |
my $lowml=0; | |
if (defined $ml && $ml > 1 && $ml < 150) { $lowml=1; } | |
if (defined $cnt && defined $mg) { | |
say "1 [$i] [$whi${mg}mg$rst x $bcya${cnt}$packstr$rst] $bmag$tit $bbla$url$rst" if $show; | |
} elsif (defined $mg) { # only mg | |
say "2 [$i] [$cya${mg}mg$rst x ?$packstr] $tit $bbla$url$rst" if $show; | |
} elsif (defined $cnt && !$$opts{weight}) { # only cnt | |
say "3 [$i] ${red}[?mg x $bcya$cnt$packstr$rst] $tit $bbla$url$rst" if $show; | |
} else { | |
say "BB ${whi}[$asin] $rst$tit" if $verbose > 1; | |
$packs = .9 if !defined $packs; | |
$price = 0 if !defined $price; | |
$cnt = 1 if !defined $cnt; | |
if (!defined $ml) { $mlstr = "$red?ml$rst "; $ml=1; } | |
else { $mlstr = "${whi}${ml}ml "; } | |
if ($$opts{pieces} || $$opts{length} || $$opts{weight}) { | |
$mlstr = ''; | |
} | |
# say $i; | |
# say $price/$packs; | |
# say "$price" if $show; | |
# say "${packs}ct"; | |
# say "${ml}"; | |
# say "Tit: $tit"; | |
# say "URL: $url"; | |
# Display product | |
printf "*[%3d] $rst%5.2f %6s ${bbla}%5s$rst %6s ${bcya}%s\n", | |
# 1 2 4 5 6 7 8 9 | |
$i, # 1 | |
$$opts{per} * $price/$packs, # 2 | |
$price, # 4 | |
"${packs}ct", # 5 | |
"$mlstr", # 6 | |
$tit # 7 | |
if $show; | |
# Display aligned URL line | |
if ($show) { | |
if (!$$opts{html}) { | |
printf " $bbla%s %s$rst\n", $asin, $url; | |
} else { | |
printf " $bbla%s <a href='%s'>%s</a>$rst\n", $asin, $url, $url; | |
} | |
} | |
my $keep = 1; | |
if ($$opts{mlmin} != $$opts{mlmax}) { | |
$keep = 0 if $ml < $$opts{mlmin}; | |
$keep = 0 if $ml >= $$opts{mlmax}; | |
} | |
for my $re (@opt_excludere) { $keep=0 if $tit =~ /$re/i; } | |
for my $re (@opt_requirere) { $keep = 0 if $tit !~ /$re/i; } | |
if (!$keep) { | |
say "${bred}Discarding: $tit $rst$url" if $verbose>0; | |
} | |
if ($keep) { | |
say "EE ${whi}[$asin] $rst$tit (${bmag}KEEP:$keep$rst)" if $verbose > 1; | |
if (exists $found_already{$asin}) { | |
say "FF ${whi}[$asin] $rst$tit (${bmag}KEEP:$keep$rst)" if $verbose > 1; | |
} else { | |
say "GG ${whi}[$asin] $rst$tit (${bmag}KEEP:$keep$rst)" if $verbose > 1; | |
$found_already{$asin}++; | |
push @bycost, { | |
cost=>$price/$packs, | |
price=>$price, | |
item=>$item, | |
}; | |
} | |
} | |
say "ZZ ${whi}[$asin] $rst$tit (${bmag}KEEP:$keep$rst)" if $verbose > 1; | |
} | |
} | |
sub main { | |
$opts = getopts(); | |
my $ml_label = $$opts{ml} ? 'ml' : ''; | |
my $aoh = csv( | |
in => $ARGV[0], | |
headers => "auto", | |
encoding => "UTF-8", | |
); # as array of hash | |
$|=1; | |
binmode *STDOUT, ':encoding(UTF-8)'; | |
say "Original headers:"; | |
say join(' ', keys %{$aoh->[0]}); | |
#say $aoh->{title}[0]; | |
#say $aoh->[1]->{title}; | |
# ############################################# | |
# FIRST PASS. PROCESSES AND REMOVES DUPLICATES: | |
for my $i (1 .. $#{$aoh}) { | |
my $item = $aoh->[$i]; | |
show_item($i, $item, { show => 0 }); | |
} | |
# ################################################ | |
# SECOND PASS. PROCESSES (again, ugh) AND DISPLAYS | |
if ($$opts{price}) { | |
@bycost = sort { $a->{price} <=> $b->{price} } @bycost; | |
} else { | |
@bycost = sort { $a->{cost} <=> $b->{cost} } @bycost; | |
} | |
# @bycost = sort { $a->{price} <=> $b->{price} } @bycost; | |
say "${whi}Price per $$opts{per} count$rst" if $$opts{per} != 1; | |
print "<pre>" if $$opts{html}; | |
printf "$whi %3s %5s %6s %5s %6s %s$rst\n", | |
'#', '$/ct', '$', 'ct', $ml_label, ''; | |
for my $i (0 .. $#bycost) { | |
show_item($i, $bycost[$i]->{item}); | |
} | |
say "</pre>" if $$opts{html}; | |
} | |
sub usage { | |
print <<~'EOT'; | |
--verbose -v increase verbosity | |
--help -h | |
--html output html | |
--mlmin filter milliliters | |
--mlmax filter milliliters | |
--price Sort by price only (don't calculate cost/item) | |
--per This just multiplies the final cost/unit | |
(Useful if you're getting small values in searches, like | |
$.01234/ea, and want to force --per 100 which will change | |
the normal $cost/$total to 100*$cost/$total) | |
--ml Milliliters/volume mode (same as --cc) | |
--cc Same as --ml | |
--pieces Things in "packs,sets,pcs", etc. | |
--weight Things with weight | |
--length (Inches/in/" is new, is converted to feet, and might | |
not be working). | |
-er {x} --excludere {x} Only show matches with {x} (in title) | |
-re {x} --requirere {x} Only show matches w/o {x} (in title) | |
--prime Only da Prime results | |
Egg zamples: | |
1. A simple search and processing: | |
$ amazon-buddy -n 300 products -k '150ml syringes' | |
$ amazon-price-examine {products.csv from above} 2>&1 | less -R | |
2. Join some searches (the sort|uniq isn't really necessary, | |
since we remove duplicates based on amazon-id ("asin"). | |
$ mkdir amazon-syringes && cd amazon-syringes | |
$ amazon-buddy -n 300 products -k '150ml syringes' | |
$ amazon-buddy -n 300 products -k '250ml syringes' | |
$ cat products*.csv | sort | uniq > uniq.csv | |
$ amazon-price-examine {uniq.csv} 2>&1 | less -R | |
3. A search showing the cost per 10, and --pieces to not do ml, mg, etc. | |
$ amazon-price-examine -per=10 --pieces products.csv | |
EOT | |
} | |
sub getopts { | |
my %opts; | |
$opts{verbose} = 0; | |
$opts{mlmin} = 0; | |
$opts{mlmax} = 0; | |
$opts{mgmin} = 0; | |
$opts{mgmax} = 0; | |
$opts{pieces} = 0; | |
$opts{weight} = 0; | |
$opts{length} = 0; | |
$opts{prime} = 0; | |
$opts{per} = 1; | |
$opts{price} = 0; | |
# $opts{infn} = "foo.dat"; | |
GetOptions(\%opts, | |
"verbose|v+", | |
"help|h", | |
"html", | |
"mlmin=i", | |
"mlmax=i", | |
"per=i", | |
"price", | |
"ml", | |
"cc", | |
"pieces|pc|pcs", | |
"weight", | |
"length|len", | |
"excludere|er=s" => \@opt_excludere, | |
"requirere|re=s" => \@opt_requirere, | |
"prime", | |
#"length=i" => \$opts{length}, # numeric | |
# "i|file=s" => \$opts{infn}, # string | |
) or die("Error in command line arguments\n"); | |
if ($opts{help}) { usage(); exit 0; } | |
uncolor() if $opts{html}; | |
# Set option consequences: | |
$opts{cc} = 1 if $opts{ml}; | |
$opts{ml} = 1 if $opts{cc}; | |
if (!$opts{ml}) { | |
if (!$opts{length}) { | |
if (!$opts{weight}) { | |
$opts{pieces}=1; | |
say STDERR "Defaulting to 'Pieces' (pcs, sets, packs, etc.)"; | |
} | |
} | |
} | |
$verbose = $opts{verbose}; | |
return \%opts; | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment