postimg
Dec 2009 16

Using Perl To Get Free MP3s!0

Posted In Perl By John Hass

In this article I am going to code up a program that will actually download music from free.napster.com and give you the 32k mp3 file contained within.  So without further ado, let the Free mp3’s reign.

Using libwww, swftools, and some trickery we can easily download mp3’s from free.napster.com.  I am using Linux, but all the requirements for this application should work in Windows.

I am calling my application getTunes.pl for reference. The full source will be attached to this Blog posting.

Create the document

#!/usr/bin/perl
use LWP;
use Time::HiRes qw(gettimeofday);
use XML::Simple;
use Data::Dumper;

The above are the only required Perl libraries, and on my Ubuntu machine all were installed by default.

We have one requirement for a binary swfextract. You can get swftools from: http://www.swftools.org/

Our code requires the path to swfextract

#!/usr/bin/perl
use LWP;
use Time::HiRes qw(gettimeofday);
use XML::Simple;
/tuse Data::Dumper;
$swfextract = "/usr/bin/swfextract";
if (!-e $swfextract) {
print "You must have swftools installed to use this application\n";
exit;
}

The code does a double check to make sure that swfextract is located where you said it was (that is what -e does stands for exists).

We need to create a browser object and an XML object

$browser = LWP::UserAgent->new;
$xml = new XML::Simple;

These will get used later on in the code.

our application is called like ./getTunes.pl song_id so for example. ./getTunes.pl 28908362 will download the Song “Fireflies by Owl City”

Our code needs to make sure that the user passes an argument.

$song_id = $ARGV[0];
if ($song_id eq "") {
print "You must include the sond id to download\n";
exit;
}

Our code includes 2 subroutines the main purpose of them is to generate random information

sub random {
$min = shift;
$max = shift;
$random = rand();
return (($max-$min + 1)*$random+$min);
}
sub randomID {
#lifted from: http://www.codeproject.com/KB/perl/perl_randomstring.aspx
my $passwordsize = shift;
my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9);
my $randpassword = join '', map $alphanumeric[rand @alphanumeric], 0..$passwordsize;
return $randpassword;
}

The first one takes two arguments, minimum number and maximum number it then uses Perl’s built in rand() function to create a decimal number

The second generate a random alpha numeric string. It was quicker to google this then writing my own, but you get the idea.

In order to download a song we have to make 3 separate connections to napster in order, or the song won’t download, each time you connect you must send Napster different headers.

I will outline these connections now.

$r = random();
my @headers1 = (
'User-Agent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.11',
);
$url1 = "http://napsterweb.112.2o7.net/b/ss/napsterweb/1/G.9p2/s68966730169826?[AQB]&ndh=1&t=$Day/$Month/$Year%201%3A9%3A41%204%20300&pageName=Napster%20Web%20-%20Album&g=http%3A//free.napster.com/view/album/index.html%3Fid%3D12601251&r=http%3A//free.napster.com/&ch=Napster%20Web&events=event2&cc=USD&Sc3=Returning%20Anonymous&v3=Play_Track_21470573_http%3A//free.napster.com/view/album/index.html&v4=Returning%20Anonymous&v5=US&s=800x600&c=24&j=1.3&v=Y&k=Y&bw=640x480&bh=$r&p=Shockwave%20Flash%3B&[AQE]";
$resp=$browser->get($url1,@headers1);

This code may look scary, but there is only a few things needed to make it function correctly, to me this is my way of saying “Hello Napster I am here”.
You have to fill in $Day,$month,$year (see full source for that code) $r which is simply a random number.

Then using Perl we pass the query off to napster, and we don’t care what napster says back, in fact it’s a picture, a picture of nothing.

$random_play = random(10000000,99999999);
$id = randomID(43);
$cookie = "L115=1.1190942847196; SCD=r%3D0%26ch%3DNapster%2520Web%2520Player%26time%3D$time%26FPF%3D0%26ter%3D0%26utype%3D0%26FUID%3D-%26$id%3Dnl; NQ=%3Fquery%3DCooler+Online%26type%3Dartist; s_cc=true; s_sq=%5B%5BB%5D%5D; COUNTRYCODE=US";
my @headers2 = (
'User-Agent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.11',
'Host' => 'free.napster.com',
'Accept' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
'Accept-Language','en-us,en;q=0.5',
'Accept-Charset','UTF-8,*',
'Keep-Alive', '30',
'Proxy-Connection','keep-alive',
'X-Requested-With','XMLHttpRequest',
'X-Prototype-Version','1.4.0',
'Referer',"http://free.napster.com/player/?play_id=$random_play&type=track",
'Cookie',$cookie,
);
$url2 = "http://free.napster.com/playXML/track/$song_id?r=$r";
$resp=$browser->get($url2,@headers2);
$data = $xml->XMLin($resp->content);

The second is a query is to get the xml output from Napster with the all important pld, the only thing new here to report is the random_play option on the referrer this is just some more trickery, and the $id which makes use of our alpha numeric string.

you can see above that we loaded the response right into xml. If you were to do a data dump you would see this

$VAR1 = {
'clip' => {
'track_number' => '9',
'album_name' => 'Ocean Eyes',
'album_id' => '13291611',
'track_id' => '28908362',
'album_price' => '9.95',
'image_max' => 'http://images.napster.com/mp3s/2462/resources/194/471/files/194471299.jpg',
'artist_id' => '12425061',
'pld' => 'UmFuZG9tSVZCAI0C.XUUM.tWuyOSGlVb9a8s1hy9sgXORKsWYPpLIwTFi9z6IcXOxX6158hu9Ig.akD1tQXHugZfp15bmWvvZQc.qVhuw8BSql35_Lg6pNB3ZVaRYbi5',
'is_free' => 'Y',
'afs' => 'Y',
'streaming_is_active' => 'Y',
'explicit' => 'N',
'track_price' => '1.29',
'artist_name' => 'Owl City',
'duration' => '03:48',
'display_name' => 'Fireflies',
'image' => 'http://images.napster.com/mp3s/2462/resources/194/471/files/194471301.jpg',
'can_purchase' => 'Y',
'genre_id' => '1'
},
'content_title' => ''
};

As you can see there is lots of juicy information in this, I only care about the pld and the display_name

$pld=$data->{clip}->{pld};
$name=$data->{clip}->{display_name};

The last query is the file download, it is not too scary.

$cookie2 = "L115=1.1190942847196; SCD=r%3D0%26ch%3DNapster%2520Web%2520Player%26time%3D$time%26FPF%3D0%26ter%3D0%26utype%3D0%26FUID%3D$id-%26uac%3Dnl; NQ=%3Fquery%3DCooler+Online%26type%3Dartist; s_cc=true; s_sq=%5B%5BB%5D%5D; COUNTRYCODE=US; NTLG=UmFuZG9tSVZQv5fLKbtRWco69MsjQmjCc.i8u9_1Z1ThyeJxaqPSfQ--%211";
my @headers3 = (
'User-Agent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.11',
'Host' => 'sms.napster.com',
'Accept' => 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
'Accept-Language','en-us,en;q=0.5',
'Accept-Charset','UTF-8,*',
'X-Requested-With','XMLHttpRequest',
'X-Prototype-Version','1.4.0',
'Referer',"http://free.napster.com/player/?play_id=$random_play&type=track",
'Cookie',$cookie2,
);
#get the file
$url3="http://sms.napster.com/cgi-bin/fetchncomurl.cgi?clip=$pld&suf=.swf";
$resp=$browser->get($url3,@headers3);

Not too much different then the rest of the queries, but you notice that it looks like I am downloading a swf?

$url3="http://sms.napster.com/cgi-bin/fetchncomurl.cgi?clip=$pld&suf=.swf";

That is because I am downloading a swf, so before we get too much into that lets save the file.

open (SONG, ">$song_id.swf");
print SONG $resp->content;
close(SONG);

this will create a file called 28908362.swf we now need to extract the mp3

`$swfextract  -m $song_id.swf -o $name.mp3`;
unlink("$song_id.swf");

Your mp3 is now created.

So the big question left now is. How do I get song id’s? Simply go to free.napster.com click play on the song you want and then in the window get the play_id.

napsterplay_id

That is it for now!

Source Files: getTunes.zip (7)

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay
  • email
  • LinkedIn
  • MySpace
  • PDF
  • Reddit
  • RSS
  • Slashdot
  • StumbleUpon
  • Technorati
  • Twitter

Leave a comment

Get Adobe Flash playerPlugin by wpburn.com wordpress themes