in reply to Next 50 array elements during each loop?

I have all of it working except the looping through @vidids.

Im not sure you have the rest working either. I use Oauth2, and so include a Authorization: Bearer ... header rather than a api key via LWP.

You dont check for an error return, part=items(viewCount) returns content of

"error": { "errors": [ { "domain": "youtube.part", "reason": "unknownPart", "message": "items(viewCount)", "locationType": "parameter", "location": "part" } ], "code": 400, "message": "items(viewCount)" }
and a return code of 400. You will want part=statistics instead. To limit the fields returned you use the fields= parm. And there is no requirement that the api returns all of the ids requested or in any certain order. you will want to get the id field as well fields=items/id,items/statistics/viewCount So you will want to save both the id and viewcount. a hash works well for this.
sub api_videos { use Data::Dumper; my $ua=LWP::UserAgent->new(keep_alive=>1,timeout=>100); my @vidlist0=qw/ bH4tEHg-Wtc ShI5jhe3bi4 bbpyN89Vquk EgJ5GGD_2QQ YoRnMC2MlqU 7M39G0Yxy +dk 1ov2NQ2Sz5w HmourJ3O6Ss sWSzjBPI1cY czt_a0fKvFA x6GDUIUHSqg 4oEWS33lt9M KlTwG3UNqE8 ACVgSl9OpIQ mbsGOyNjsNQ L2qpMI6mN +pU 6a1Ziw0-4X4 3Z08nsbhlAY vMLGUrVyyMk pjmyy0qKN2o qyXxrPTcFKE d2SFFHlHNCY akSp8m4JAnY AEDw975DAlM ypl033on69k LM7GxrK-h +go L6qq5aVOEmc tGEnzlNkGKI Aq2QQYY8YSA ZnnzFSGGJP4 Nt1qRbAlrCs cnGQ2nE3USI YuzE5jomGLk wSz2kCpuZ6E v40RcxCpvgM bUVLymf4c +00 -_rQwhvJDd4 jmaB41hx8b0 lcLSo0dijv8 HtBbRvj2cfc lQVBX6aqC8o rbq4RZGP8 +YU qy5NfKg1fJo jtjOcSBBoiE aRhqb-pljGk iRbqaMfpOrA tSKGYQFwAHs 7sHXl8q7u +DY d4u8Wj0xY7A Rtzk1I0BhSI x /; my $vidlist=[]; my $n=0; my @vidlists=(); my $testct=10; my $back={}; for my $vid (@vidlist0){ $n++; if ($n>$testct) {push @vidlists,$vidlist; $n=1; $vidlist=[];} push @{$vidlist},$vid; } push @vidlists,$vidlist; my $head='https://www.googleapis.com/youtube/v3/videos?fields=items/ +id,items/statistics/viewCount&part=statistics&id='; for my $vl (@vidlists){ my $getline=$head.join(',',@{$vl}); my $req = new HTTP::Request (GET => $getline ,HTTP::Headers->new( 'Authorization' + => 'Bearer '.$agrp->{access_token} ) ); my $request = $ua->request ($req); unless ($request->is_success) { print "\n** Can't get -- :".$request->status_line."\n"; print $getline."\n"; } else { my $jsondata; eval{ $jsondata=$json->allow_nonref->decode($request->content +);} ; if ($@) { print 'json decode error:'.$@ ."\n"; } elsif ($jsondata->{error}) { print Dumper(\$json); } else { for my $item( @{$jsondata->{items}} ) { $back->{$item->{id}}=$item->{statistics}{viewCount}; } # item } # no error } # success } # vl for my $vid(@vidlist0) { unless (exists $back->{$vid} ) {print "video $vid not returned\n";} } print Dumper({back=>$back}); }
result
video x not returned $VAR1 = { 'back' => { 'bH4tEHg-Wtc' => '39', 'EgJ5GGD_2QQ' => '40', 'mbsGOyNjsNQ' => '150', 'bUVLymf4c00' => '51', 'qy5NfKg1fJo' => '20', 'bbpyN89Vquk' => '22', 'Rtzk1I0BhSI' => '87', 'rbq4RZGP8YU' => '60', 'qyXxrPTcFKE' => '46', 'ZnnzFSGGJP4' => '66', 'AEDw975DAlM' => '69', '7M39G0Yxydk' => '31', 'ACVgSl9OpIQ' => '89', 'wSz2kCpuZ6E' => '52', 'L6qq5aVOEmc' => '69', 'cnGQ2nE3USI' => '43', 'v40RcxCpvgM' => '50', 'ypl033on69k' => '63', 'tSKGYQFwAHs' => '51', 'jtjOcSBBoiE' => '170', 'pjmyy0qKN2o' => '236', 'vMLGUrVyyMk' => '151', 'LM7GxrK-hgo' => '405', 'ShI5jhe3bi4' => '30', 'jmaB41hx8b0' => '186', 'L2qpMI6mNpU' => '162', 'czt_a0fKvFA' => '152', '1ov2NQ2Sz5w' => '19', 'sWSzjBPI1cY' => '58', 'YuzE5jomGLk' => '32', 'Nt1qRbAlrCs' => '57', 'akSp8m4JAnY' => '131', 'x6GDUIUHSqg' => '77', 'lcLSo0dijv8' => '62', 'lQVBX6aqC8o' => '36', 'tGEnzlNkGKI' => '93', 'aRhqb-pljGk' => '181', 'KlTwG3UNqE8' => '49', 'd2SFFHlHNCY' => '48', '-_rQwhvJDd4' => '108', '6a1Ziw0-4X4' => '71', 'HtBbRvj2cfc' => '52', 'd4u8Wj0xY7A' => '51', 'YoRnMC2MlqU' => '59', '3Z08nsbhlAY' => '86', '7sHXl8q7uDY' => '17', 'HmourJ3O6Ss' => '147', '4oEWS33lt9M' => '38', 'Aq2QQYY8YSA' => '101', 'iRbqaMfpOrA' => '51' } };

Replies are listed 'Best First'.
Re^2: Next 50 array elements during each loop?
by Bman70 (Acolyte) on Jun 03, 2017 at 18:36 UTC
    Great catch, you're right the part is statisics, and fields are items>statistics>viewCount. I constantly duplicate my .pl file to edit while saving my tracks, so older versions might not have all the URL syntax correct. Of course in this case it's just the loop I'm after

      Ive been programmatically watching my view counts since 2007. Since they just changed the API yet again and I had to modify the code again it stood out. I am currently checking about 1000 videos a few times an hour.

      Since you dont use LWP::UserAgent and so dont have access to the return code you need to test for valid json, i do that via the eval to trap the die signal. It is not uncommon for the api to barf or timeout and return improper json.

      For the same reasons you also need to test for the error case where no items array gets returned. While not as common as barfing there have been times the api seems to have forgotten that statistics was a valid part for a while.

      And if a video gets deleted or marked private there will be no entry in the items array for that video, so the hash containing the id and count is useful. And as i pointed out at times the order of the items array has also gotten changed from the order i asked for, so the id/viewcount hash is also useful in that case rather than rely on a 1-1 correspondence to the asking order that your counts array only provides.

      Another thing to be aware of is negative deltas on the view count. It seems at times they will back out some update and the delta will be negative, then an hour or so later they will reapply that transaction set and cancel it out. Negative deltas can also happen if they decide views were programmatically generated somehow.

      In regards to versioning you may wish to consider some versioning system instead of relying on copies. They made me use CVS at work about 17 years ago, so ive been using it at home since then as well. I dont do fancy things with it so i havent felt any need to move to one of the more fancy systems like git and loose my prior history. I commit whenever i have decently working code and that allows me to back out changes or see what i have changed since the last commit. It also allows me to test on one box and then easily roll out the updates to the "production" box when i am finished. And as i have a mixture of linuxen and win boxes it also takes care of the proper \n for the architecture when i checkout or update.