You are here: Home / Blogs / Grab Packt With Groovy

Grab Packt With Groovy

Automatically claim Packt's free e-books with a Groovy program.

Introduction

Packt Publishing has launched a new programme called "free learning offer"; each day they put an e-book for free on their website to download: one only needs to login to Packt's website and click on the "claim your free book" link.

Following Grab Packt with Racket, here is the Groovy version, to autmotically add the e-book to your Packt account for later downloads.

The Code

The code is in public domain. You can get it directly from is.gd/isbviw or from my github gist.

For this to work you need to replace YOUR-EMAIL-ADDRESS (line 26) and YOUR-PASSWORD (line 27) with reasonable values. If you wish to run this from shell/cron remember to add #! /usr/bin/env groovy to the top of the file.

The script is completely self-contained as @Grab annotation on line 4 fetches the dependencies it requires.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
 * @author Bahman Movaqar <Bahman AT BahmanM.com>
 */
@Grab('org.jsoup:jsoup:1.8.2')
import static org.jsoup.Jsoup.parse

def cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL)
CookieHandler.setDefault(cookieManager)
def doc = parse(
  new URL('https://www.packtpub.com/packt/offers/free-learning').text
)
2.times { // a weird hack! to make this work on slow connections
  doLogin(
    loginParams(doc.select('input[type=hidden][id^=form][value^=form]')?.val())
  )
}
claimBook(
  doc.select('a.twelve-days-claim').attr('href'),
  CookieHandler.getDefault().cookieStore.cookies
)
println('Claimed! Login to Packt website to download the book.')

///////////////////////////////////////////////////////////////////////////////
def loginParams(formBuildId) {
  [
    email: 'YOUR_EMAIL_ADDRESS',
    password: 'YOUR_PASSWORD',
    op: 'Login', 
    form_id: 'packt_user_login_form',
    form_build_id: formBuildId ?: ''
  ].findAll { k, v -> v }.collect { k, v -> 
    "$k=${URLEncoder.encode(v, 'UTF8')}"
  }.join('&')
}

///////////////////////////////////////////////////////////////////////////////
def doLogin(loginParams) {
  new URL(
    'https://www.packtpub.com/packt/offers/free-learning'
  ).openConnection().with {
    requestMethod = 'POST'
    setRequestProperty('Content-Type', 'application/x-www-form-urlencoded')
    doOutput = true
    doInput = true
    allowUserInteraction = true
    outputStream.withWriter { w -> w << loginParams }
    connect()
    if (parse(inputStream.text).select('div.error'))
      throw new Exception("Failed to login.")
  }
}

///////////////////////////////////////////////////////////////////////////////
def claimBook(bookUrl, cookies) {
  new URL(
    "https://www.packtpub.com${bookUrl}"
  ).openConnection().with {
    requestMethod = 'GET'
    cookies.each { setRequestProperty('Cookie', it.toString()) }
    connect()
    content
  }
}

How To Run

Provided that you have installed Groovy (if you're on Linux/Mac, I'd very strongly suggest doing that with GVM), get the code by copy-pasting or directly from is.gd/isbviw and simply run (remember to save the file as GrabPackt.groovy):

$ groovy GrabPackt.groovy
Related content
Grab Packt With Racket
Shahram says:
Jul 01, 2015 01:39 AM

Splendid, Thanks Sir!

Yoshihisa Okue says:
Nov 19, 2015 05:59 AM

This program does not run the Javascript properly. I tried to use jQuery but get syntax error.

Bahman Movaqar says:
Nov 19, 2015 08:35 AM

I don't understand. Can you be more specific? Why should it "run Javascript"? What does jQuery have to do with this?

Add comment

You can add a comment by filling out the form below. Plain text formatting.

Question: What is 1 + 5 - 6 ?
Your answer: