Friday, 10 April 2020

Get Netbeans browser debugging going with PHP and Xdebug

This was done with Ubuntu v.19.10 and Netbeans v.11.
-got this going in both Firefox and Chromium browsers



Make sure xdebug is installed
sudo apt-get install php-xdebug
-check this works OK in some phpinfo output in a web page


-in your browser, install the XdebugHelper extension/add on
-make sure in the extension's Preferences/Options, set the session key to the preset for Netbeans




Firefox view




Chromium view



-add these lines in the PHP ini file for Xdebug, e.g.
in /etc/php/7.3/apache2/conf.d/20-xdebug.ini:
xdebug.remote_enable=on
xdebug.idekey = netbeans-xdebug
xdebug.remote_host = localhost
xdebug.remote_port = 9000
xdebug.remote_handler = dbgp


You may also want to check your Apache php.ini file for output_buffering=off.

Restart Apache:
systemctl restart apache2

You might have to restart the browser and Netbeans to get this all going
In Netbeans, make sure your project's Properties has the PHP version as the right one (e.g. 7.3). Also the run configuration should be "Local web site (running on local web server" 
Add a breakpoint in a margin
Go to Debug >Debug Project
In browser, go to a page. Click the little extension bug icon, choose Debug





Refresh the page in the browser.

Go back to Netbeans.
-the code execution in the IDE should stop at the line, and highlight the breakpoint line green (with dark theme)
Push F5 / F8 to carry on execution


Saturday, 2 March 2019

A Desktop GUI form with the PHP UI extension

Intro


As a follow on to last week's post, this week I am again exploring out the PHP UI extension which lets you create desktop PHP 7 programs. My mission this time is set up a basic form for letting you type some inputs in boxes, push a button and see an output somewhere else.

What's up, doc?


OK, so the only real documentation the UI extension seems to have (at the time of writing) are some pages on php.net website. There is also the "gallery.php" example file from the project itself, which shows you ways to put elements on a GUI window.



Keep It Simple, Stupid


I just want to make a simple window with a form and button. So, after playing around with some of the ways to do things demonstrated in the "gallery.php", I found out a way for beginners to do things but it's not perfect.

A beginner has a choice of trying things with Box, Group, Grid and Form elements. The Grid element is especially useful because it lets you set a size on elements it will contain, and position it in relation to other elements. However, Form is the thing to stick with when you first try things out. The full source code for the example can be found at the end of this blog post.

At the top of your PHP code file, you will need to insert "use" statements for the elements you're going to put in your window, e.g.

use UI\Window;
use UI\Controls\Form;



Showing Good Form


A Form element is created like this, and you can append more elements within it:

$entryForm1 = new Form();
$entryForm1->setPadded(true);
$entryForm1->append("", new Label("Enter text to match with a reg ex"));


I also want to multiline (MultilineEntry) inputs, which I'll append to the form later:

$haystackEntry = new MultilineEntry(MultilineEntry::Wrap);
$outputEntry = new MultilineEntry(MultilineEntry::Wrap);


I further have the need to put "spacing" rows between lines. I've tried various ways to do this but the quick way to this is just to append a blank Label, which act like an empty row, e.g.

$entryForm1->append("", new Label(""));

Push My Button


It's easy to add a button to a form. However, I need a button that will execute an specific action once its event is triggered, i.e. the button is clicked. To do this, it looks like we have extend the UI's Button class and put in the functionality we need it to do for us. Here's my effort:

/**
 * The class extends the UI's Button class, so there is an onClick method we can
  * use as an event handler.
 */
class ButtonSubmit extends Button {
   
    public function __construct(string $text,
        MultilineEntry $inputHaystackCtrl,
        MultilineEntry $inputRegexCtrl,
        MultilineEntry $outputCtrl
    ) {
        $this->inputHaystackCtrl = $inputHaystackCtrl;
        $this->inputRegexCtrl = $inputRegexCtrl;
        $this->outputCtrl = $outputCtrl;

        parent::__construct($text);
    }
   
    /**
     * When the button is clicked, take the "haystack" text from one entry input
     * and try to match it with the regular expression in the other entry input.
     * Show a result in the output input.
     */
    protected function onClick() {
        $matches = "";
        $haystackString = $this->inputHaystackCtrl->getText();
        $regExToMatch = $this->inputRegexCtrl->getText();
        preg_match($regExToMatch, $haystackString, $matches, PREG_OFFSET_CAPTURE);
        $outputMessages = ["You entered: " . $haystackString . "."];
        $outputMessages[] = "Number of matches: " . count($matches);

        $this->outputCtrl->setText(implode("\n", $outputMessages));
    }

    private $inputHaystackCtrl;
    private $inputRegexCtrl;
    private $outputCtrl;
};


Then add my button to the form:

$entryForm1->append("", $btnSubmit);

Open the Window


$window = new Window("Regex form", new Size(640, 480), true);
$window->add($entryForm1);

Then call the window show() method, and start the UI interaction loop:

UI\run();

When you run your php program, you'll see your form window appear. You'll also probably notice that the button element is unusually wide; we can't resize it. I did say the Form element was good to learn but not perfect ;-)


Get Trigger Happy


Enter some text in the "Text" mulitline input. The click the Submit button to see if the event gets triggered.


So, there you have it - a simple form with a button that executes an event. It might not be a competitor for Windows Forms, but it's a start.

Full Source Code


<?php
use UI\Size;
use UI\Window;
use UI\Controls\Form;
use UI\Controls\Button;
use UI\Controls\MultilineEntry;
use UI\Controls\Label;


// Lets make a button with custom features to handle inputs
/**
 * The class extends the UI's Button class, so there is an onClick method we can
  * use as an event handler.
 */
class ButtonSubmit extends Button {
   
    public function __construct(string $text,
        MultilineEntry $inputHaystackCtrl,
        MultilineEntry $inputRegexCtrl,
        MultilineEntry $outputCtrl
    ) {
        $this->inputHaystackCtrl = $inputHaystackCtrl;
        $this->inputRegexCtrl = $inputRegexCtrl;
        $this->outputCtrl = $outputCtrl;

        parent::__construct($text);
    }
   
    /**
     * When the button is clicked, take the "haystack" text from one entry input
     * and try to match it with the regular expression in the other entry input.
     * Show a result in the output input.
     */
    protected function onClick() {
        $matches = "";
        $haystackString = $this->inputHaystackCtrl->getText();
        $regExToMatch = $this->inputRegexCtrl->getText();
        preg_match($regExToMatch, $haystackString, $matches, PREG_OFFSET_CAPTURE);
        $outputMessages = ["You entered: " . $haystackString . "."];
        $outputMessages[] = "Number of matches: " . count($matches);

        $this->outputCtrl->setText(implode("\n", $outputMessages));
    }

    private $inputHaystackCtrl;
    private $inputRegexCtrl;
    private $outputCtrl;
};

/**
 * Let's build a Wdindow with a form in it
 */
function getRegexFormWindow() {
    $haystackEntry = new MultilineEntry(MultilineEntry::Wrap);
    $regExEntry = new MultilineEntry(MultilineEntry::Wrap);
    $regExEntry->setText("/(foo)(bar)(baz)/");
    $outputEntry = new MultilineEntry(MultilineEntry::Wrap);
    $btnSubmit = new ButtonSubmit("Submit", $haystackEntry, $regExEntry, $outputEntry);

    $entryForm1 = new Form();
    $entryForm1->setPadded(true);

    $entryForm1->append("", new Label("Enter text to match with a reg ex"));
    $entryForm1->append("", new Label(""));
    $entryForm1->append("Text", $haystackEntry, true);

    $entryForm1->append("", new Label(""));
    $entryForm1->append("Reg ex", $regExEntry, true);
   
    $entryForm1->append("", new Label(""));
    $entryForm1->append("", $btnSubmit);

    $entryForm1->append("", new Label(""));
    $entryForm1->append("Output", $outputEntry, true);
    $entryForm1->append("", new Label(""));

    $window = new Window("Regex form", new Size(640, 480), true);
    $window->setMargin(true);
    $window->add($entryForm1);
    return $window;
}

$regExWindow = getRegexFormWindow();
$regExWindow->show();

UI\run();



Thursday, 28 February 2019

Desktop PHP 7 with the UI extension & libui

Introduction


You may be like me and want to write your own desktop GUI programs with PHP 7 (i.e. not web programs in a browser). There are various options out there but many seem to have been abandoned or stuck with support only at PHP 5. In my search for desktop goodness I found the PHP extension "UI", which is a wrapper around a neat C library for creating desktop programs, "libui". The UI extension has the advantage of working with PHP 7.x.

The libui project can be found here.

 The PHP UI extension project can be found here.

What follows are instructions on how to first install libui, then the UI extension for PHP. I'm assuming you've got a bog standard PHP 7.2 set up already. I've tested this all out in Ubuntu 18.04 (and Lubuntu). I'm using the vim editor here, but you can try whichever editor suits you.

The C library, libui


On the command line, install packages:

sudo apt-get install build-essential cmake pkg-config libgtk-3-dev re2c git php7.2-dev


Then let's clone the libui project:

cd /opt
git clone https://github.com/andlabs/libui.git
cd libui
git checkout alpha3.5


And then compile the project:



mkdir build
cd build
cmake ..
make


Try it out:

View one of the example source C files that generates a windows with controls:

vim ../examples/controlgallery/main.c

Compile the example libui programs:


make examples
ls out

--> see the compiled files in the out directory

To run one:
out/controlgallery
--> see a window appear with example controls





Make the libui library available elsewhere:

sudo install ui.h /usr/local/include/;
sudo install ui_unix.h /usr/local/include/;
sudo install build/out/libui.so /usr/lib/;
sudo install build/out/libui.so.0 /usr/lib/;

 

The PHP UI extension

I had problems with errors when trying to install this as a PECL extension. So instead, let's manually clone the UI project:

cd /opt
git clone git://github.com/krakjoe/ui;
cd ui


There's a fix we have to make. Change a line in a file:

vim classes/box.c

Perform a line alteration near this:

#if PHP_VERSION_ID >= 70200
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_ui_box_is_padded_info, 0, 0, _IS_BOOL, NULL, 0)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(php_ui_box_is_padded_info, 0, 0, _IS_BOOL, 0)


Configure & compile the extension:

phpize
./configure
make


Find your PHP extensions directory:

php-config --extension-dir

--> e.g. see:
/usr/lib/php/20170718

Copy the compiled file to the PHP extensions directory:

cp modules/ui.so /usr/lib/php/20170718/

Configure PHP to use the extension:

Add an "ini" file for the extension:
vim /etc/php/7.2/mods-available/ui.ini
enter:
extension=ui.so

sudo phpenmod ui

php --ri ui

-see is enabled

See example PHP code to show a window with some controls:

vim examples/gallery.php

Run the example PHP file and try stuff out with your new PHP desktop greatness!

php examples/gallery.php




Next time I'll post an entry on writing a desktop app with UI. See the next post.

Note, thanks to this forum post below for help on getting things going:
https://github.com/krakjoe/ui/issues/43
 



Monday, 18 September 2017

Using Log4Net to Log to a File for ASP.NET MVC

There are things I'd like to blog about nearly every week. This week I thought I'd actually get around to doing it, about a simple thing that really should have clearer instructions elsewhere online. We're going to use the Log4Net package to log information in an output file, in an ASP.NET MVC controller. For this example, I used log4net version 2.

First, using the NuGet package manager, install the package for log4net into your project.

Put this line in the file AssemblyInfo.cs:

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

Put this line in the file global.asax:

log4net.Config.XmlConfigurator.Configure();

Put this in the web.config file:

<configSections>
  ...
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>

  <log4net debug="true">
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Logs/log.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="100KB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
      </layout>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="RollingLogFileAppender" />
    </root>
  </log4net>

Rebuild the solution/project.

Put the logging commands in a class method, e.g. a controller:

using log4net;

public class MyController : Controller {
    ILog log = LogManager.GetLogger(typeof(MyController));
    log.Debug("* Debug message");
    log.Warn("* Warning message");
    log.Error("* Error message");
    log.Info("* Information message");
}

Run the application (push F5).

Check the project root for a new folder and a log file, named "log.log". Done!




Saturday, 24 June 2017

TimeSpans, Ticks and BigInts for C#, SQL Server & NHibernate

I'm writing this post about the data type for C# called TimeSpan. The gist of this article is that it's easy to create a TimeSpan in C# and get information about it, but it's tougher to do the same thing for storing its "ticks" units using SQL in a SQL Server database field.

A TimeSpan is not a complicated concept, you may think. It stores the number of units of time up to a point in a certain time range, usually within one day. The units are called "ticks". Here's my example, creating a TimeSpan for the time on a day of 2:30pm.

TimeSpan tSpan = new TimeSpan(14, 30, 00);
Console.WriteLine("Ticks in the TimeSpan: " + tSpan.Ticks);

The output is: 522000000000, i.e. that many ticks have occurred since the start of the time range (midnight, or 00:00:00).

Now, some of  you may have the "privilege" of using the SQL ORM for C#, NHibernate. You'll notice that what NHibernate does for storing TimeSpans in a SQL Server database is convert them into BIGINT numbers. The reason for this, I'm guessing, is that the number of ticks can end up very large for representing a TimeSpan.

If you do a SELECT query on a database table which you've mapped through NHibernate, you would see that number of ticks stored in there when you save your save your entity and execute your session transaction (i.e. ticks is 522,000,000,000).

Now, the key to converting a C# TimeSpan to a BIGINT with SQL is this next number. Once I knew it, it was plain sailing:

The number of ticks in one day = 864,000,000,000

To help you deal with that total-ticks-in-one-day figure, you also need to calculate the number of seconds in one day:

The number of seconds in one day = 86,400
(ie. 60 seconds x 60 minutes x 24 hours)

Now, when you calculate the total ticks in one day divided by the total seconds in one day, you get this number:

The number of ticks per second = 10,000,000
(i.e. 864000000000 ticks / 86400 seconds)

So, from there, stop and think. If you can get your TimeSpan's hours, minutes and seconds, all you will need to do to turn this into a total number of ticks is:

  • convert each figure's value into a total number of seconds
  • multiple the sum of all these seconds values by 10,000,000

e.g. for my 2:30pm TimeSpan:

((14 * 60 * 60) + (30 * 60) + 0 * 10000000
= 522000000000

That figure is that same as the one NHibernate stored. We're on the right track! So, let's turn this into a Transact-SQL statement, for inserting a record with those calculations in it. I'm going to declare my hour, minutes and seconds values as variables beforehand.

GO
declare @myHours int = 14;
declare @myMinutes int = 30;
declare @mySeconds int = 0;
declare @ticksPerSecond bigint = 10000000;
INSERT INTO [dbo].[MyTable]
     (
     [TimeOfDay]
     )
     VALUES
     (
     ((@myHours * 60 * 60) + (@myMinutes * 60) + (@mySeconds)) * @ticksPerSecond
     )
GO

My desired result (of 522,000,000,000) for the TimeOfDay field appears in the database correctly. T-SQL stores the value as a BIGINT in the same way that NHibernate stores a C# TimeSpan.









Friday, 9 October 2015

Crawling with OpenWebSpider

Spiderman, Where are You Coming From Spiderman?

Sometimes you just need the right tools to help you do what you want. This is especially true when the tool you are limited to has a bunch of restrictions. I ran into this particular problem the other day when I wanted to "spider" a website to find out all its possible URLs being served, including the URLs that are ignored by the usual "robots.txt" file sitting on the web server.

I actually had to find a way around the "robots.txt" file for a web site that was blocking web crawlers from finding most of the URLs that were available. Imagine a spider that is crawing through a tunnel, looking for all the tasty bugs - and there is a giant boulder in the way providing the biggest obstacle possible to getting those bugs it wants to feed on.

My requirements for a spider alternative (if possible) were:
  • free
  • no lengthy configuration
  • a GUI
  • a way of ignoring the "robots.txt" file's instructions
  • the search results in a spreadsheet file
  • able to run on Windows (and Linux too, if possible)
After some googling, I experienced true frustration at only being able to find command-line libraries or gigantic, enterprise-level Java applications. Then I came across an open source project named OpenWebSpider. The project's website is a bit confusing but it's worth persevering through.

OpenWebSpider is a neat application written in node.js, which crawls a website and saves its results to a database that you nominate. The project seems to be reasonably active and at the time of writing is hosted on SourceForge. To get the application going in Windows, first you'll need to do a few things.

Install WAMP Server

OK, so the database I wanted to store my results in was MySQL. One of the best ways to get this (and other nice bits) in Windows is to install the handy WAMP server package. (However, the providers do warn you that you might first need a Visual Studio C++ 2012 redistributable package installed.)

One you do get WAMP Server installed, you'll have a nice new "W" icon in your system tray. Click on it, then click Start All Services.



You can view the MySQL database in the phpMyAdmin interface, just to be nice and friendly. In your browser then, go to:
http://localhost/phpmyadmin

Note: if you have any troubles with phpMyAdmin, you might have to edit its config file, usually in this location:
C:\wamp\apps\phpmyadmin4.x\config.inc.php

In phpMyAdmin, create a database to store your spidering results (I've named my database "ows"). Also create a user for the database.

Install node.js

Node.js is one of the most wonderful Javascript frameworks out there, and it's what OpenWebSpider is written with. So go to the node.js project site, download the installer and run it. Check that node.js is working OK by opening a command shell window and typing the word "node".

 

Get OpenWebSpider and Create the Database's Schema

Download the OWS zip file from Sourceforge. Unzip the file. Inside the project folder, you'll see a number of files. Double-click the "openwebspider.bat" file to launch the application in a little shell window.













Then, as the readme.txt instruction file tells you:
  • Open a web-browser at http://127.0.0.1:9999/
  • Go in the third tab (Database) and configure your settings
  • Verify that openwebspider correctly connects to your server by clicking the "Verify" button
  • "Save" your configuration
  • Click "Create DB"; this will create all tables needed by OpenWebSpider

Now, check your database's new tables in phpMyAdmin:


 Start Spidering!

Go to the OWS browser view, ie. at http://127.0.0.1:9999/. Click on the Worker tab and alter any settings you might thing useful. Enter the URL of the site you want to crawl in the URL box (and make sure "http://www" is in front if needed). Then hit the Go! button.
You should then be bounced to the Workers tab. Here you'll get see real-time progress of the site crawling as it happens. You can click on the second-tier History tab if you miss the crawler finishing its run.

View Your Results

In phpMyAdmin, click on the pages table and you should automatically see a view of the crawling results. You might not need all the columns you'll see, in fact my usual SQL query to run is just something like:
select hostname, page, title from pages where hostname = 'www.website.com';



And of course, anyone with half a brain knows you can export data from phpMyAdmin as a CSV file. Then you can view your data by importing the CSV file into a spreadsheet application.


Ignore Those Pesky Robots

Please note, the next instruction is for the version of OpenWebSpider from October 2015. It probably is outdated for the latest version now.

One of the requirements was that we could bypass the "robots.txt" file, which good web crawlers by default must follow. What you'll need to do is close OpenWebSpider, and just edit one source code file. Find this file and open it up in a text editor: openwebspider\src\_worker\_indexerMixin.js.

It's a Javascript file, so all you need to do is comment out these lines (with // symbols):
 // if (!canFetchPage || that.stopSignal === true)
        // {
            // if (!canFetchPage)
            // {
                // msg += "\n\t\t blocked by robots.txt!";
            // }
            // else
            // {
                // msg += "\n\t\t stop signal!";
            // }

            // logger.log("index::url", msg);


            // callback();

            // return;
        // }

Re-save the file. Then launch OWS again, and try another search. You'll usually find the number of found URL results has gone up, since the crawler is now ignoring the instructions in the "robots.txt" file.

Everyday Use

It's a good idea to make a desktop shortcut for the "openwebspider.bat" file. So, if you want to use OpenWebSpider regularly, what you'll need to remember to do each time you need it is:
  • Start up the WAMP server in the system tray
  • On the desktop, double-click the "openwebspider.bat" shortcut icon
  • In a browser, go to localhost:9999 (Openwebspider) to run the worker
  • In a browser, go to localhost/phpmyadmin to see your results

Happy spidering!

Saturday, 28 February 2015

Python & Google Search API Requests

It's been a while since I've been able to blog something. Anyway, out of all the geeky things I could write about which I've been tinkering with (reponsive HTML email layouts, Symfony2 secure users set ups, etc)., I just thought I'd share something for a Google API that should have easy instructions for accessing it through Python somewhere but doesn't. You'll see lots of information out there about putting a CustomSearch box and results in your browser with Javascript block, but we want to do it with Python, right?

Google provide a generic "how to access Google APIs through Python" guide here:
https://developers.google.com/api-client-library/python/

However, it's not too helpful in showing you specifically how to just get Google search results out, which is what we want! It also doesn't tell you that at the time of writing Google haven't yet made a version of their module for Python 3.

Anyway, the background seems to be that years ago Google had a rather clunky XML/SOAP interface for making requests using an old Search API. Thankfully they got rid of it and replaced with a much nicer JSON API. There is a free version of this new one called the CustomSearch API, which limits you to 100 requests per day. (If you want more there is a paid version.) The catch for this is that you are also limited to only ten search results per request. I guess Google unhelpfully assume you will want to paginate search results, with ten results per page? So for example, if you want to get 100 results searching for something, you'll have to call the CustomSearch API ten times (i.e. 10 requests = 10 x 10 search results).

Shut Up & Show Me the Instructions


OK, so anyway it's Google you're dealing with. That means, if you want to use their CustomSearch API, you need a Google account. So if you haven't created a Google account yet, go ahead and create one. Then what you'll need to do is:
(a) create a Project and assign a Google API to it
(b) create a Search Engine with an ID

(a) Create a Project and assign a Google API to it


Go to the Google Developers Console and login:
https://console.developers.google.com

Click the "Create Project" button
-Enter a Project Name, e.g. "testSearch1"
-Enter a Project ID (Google will suggest one for you)

Click the "Enable an API" button
-click on the Custom Search API
Select "Credentials" in the left navigation bar under "APIs & auth"
   
Under Public API access, click on Create new Key
Then click >Server Key >Create (don't bother entering anything in optional IP addresses).
Copy the key code it gives you and save it somewhere safe.

(b) create a Search Engine with an ID


Next, go to the CustomSearch Search Engine management console page. You need to go here, because you need a search engine and its ID to be able to do Google search requests.
https://www.google.com/cse/manage/all

Click on >New search engine
-Enter a Search Engine name, e.g. Google
-Enter a site to search, e.g. www.google.com
-Choose Search the entire web but emphasize included sites
-After this is finished, in the Edit screen for the search engine you've created, click on the Search Engine ID button. Copy this ID code, you'll need it for later.



Check the available Google APIs pages and find the details for the CustomSearch API. You'll notice it has one entity: cse. This is what we're going to focus on.
https://developers.google.com/apis-explorer/#p/
https://developers.google.com/resources/api-libraries/documentation/customsearch/v1/python/latest/customsearch_v1.cse.html

Have a look in there and you will see a large number of parameters we can pass in to the entity when doing a request via the API. The only parameters we really need though are:
q - the search query string
cx - the search engine ID we created
start - the offset from the beginning of the search results.

Let's get it going with Python


OK, our goal is write a quick script in Python to run on the command line. It will make a number of requests using the Google CustomSearch API and send the results to JSON output file. (I'm assuming you're using Python 2.x and have pip installed to download your Python packages.)

Install the Google API client module:
pip install -U google-api-python-client

Edit this program below, inserting your own Project ID and Search Engine ID. I've saved it as "search_google.py", and made a new directory in my current directory named "output" first. This is where the results file will be outputted.

#!/usr/bin/env python

import datetime as dt
import json, sys
from apiclient.discovery import build


if __name__ == '__main__':
    # Create an output file name in the format "srch_res_yyyyMMdd_hhmmss.json"
    now_sfx = dt.datetime.now().strftime('%Y%m%d_%H%M%S')
    output_dir = './output/'
    output_fname = output_dir + 'srch_res_' + now_sfx + '.json'
    search_term = sys.argv[1]
    num_requests = int(sys.argv[2])

    # Key codes we created earlier for the Google CustomSearch API
    search_engine_id = '[My Search Engine ID]'
    api_key = '[My Project API Key]'
   
    # The build function creates a service object. It takes an API name and API
    # version as arguments.
    service = build('customsearch', 'v1', developerKey=api_key)
    # A collection is a set of resources. We know this one is called "cse"
    # because the CustomSearch API page tells us cse "Returns the cse Resource".
    collection = service.cse()

    output_f = open(output_fname, 'ab')

    for i in range(0, num_requests):
        # This is the offset from the beginning to start getting the results from
        start_val = 1 + (i * 10)
        # Make an HTTP request object
        request = collection.list(q=search_term,
            num=10, #this is the maximum & default anyway
            start=start_val,
            cx=search_engine_id
        )
        response = request.execute()
        output = json.dumps(response, sort_keys=True, indent=2)
        output_f.write(output)
        print('Wrote 10 search results...')

    output_f.close()
    print('Output file "{}" written.'.format(output_fname))


Run the program on the command line with the format:
python search_google.py "[my search term]" [number of requests x 10]
e.g.
python search_google.py "vintage tiddlywinks" 3

Your JSON file should be outputted in the output directory you created, containing your search results.