Programming languages

Minimal Koa.JS example with Router & Body parser

This is the minimal Koa.JS application which I use as a template for new NodeJS webserver applications.

#!/usr/bin/env node
const router = require('koa-router')();
const koaBody = require('koa-body');
const Koa = require('koa');
const app = new Koa();

app.use(koaBody());

router.get('/', async ctx => {
    ctx.body = "Hello world";
});

app.use(router.routes());

if (!module.parent) app.listen(3000);

Install the requirements using

npm i --save koa koa-router koa-body

and run using

node index.js

assuming you have saved our code from above in index.js.

Now (with the node index.js command still running) go to http://localhost:3000 . You should see Hello world there. Now it’s your turn to continue on your endeavour to develop the world’s greatest webservers 🙂

Posted by Uli Köhler in Javascript, NodeJS

What does ‘if (!module.parent)’ mean in NodeJS?

In NodeJS applications you often see code like

if (!module.parent) {
    app.listen(3000);
}

This means: Run app.listen(3000) only if you are running the file

Suppose this code is in index.js. In this case, the code will only be executed if you run index.js directly (i.e. using node index.js) and not if index.js is required from another file (by require('./index.js');).

If index.js is required from another Javascript module (i.e. file), module.parent will be set to that module.

Posted by Uli Köhler in Javascript, NodeJS

How to get schema of SQLite3 table in Python

Also see How to show table schema for SQLite3 table on the command line

Use this function to find the table schema of a SQLite3 table in Python:

def sqlite_table_schema(conn, name):
    """Return a string representing the table's CREATE"""
    cursor = conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
    sql = cursor.fetchone()[0]
    cursor.close()
    return sql

Usage example:

print(sqlite_table_schema(conn, 'commands'))

Full example:

#!/usr/bin/env python3
import sqlite3
conn = sqlite3.connect('/usr/share/command-not-found/commands.db')

def sqlite_table_schema(conn, name):
    cursor = conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
    sql = cursor.fetchone()[0]
    cursor.close()
    return sql

print(sqlite_table_schema(conn, 'commands'))

which prints

CREATE TABLE "commands" 
           (
            [cmdID] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
            [pkgID] INTEGER NOT NULL,
            [command] TEXT,
            FOREIGN KEY ([pkgID]) REFERENCES "pkgs" ([pkgID])
           )

 

 

Posted by Uli Köhler in Python, SQLite

How to fix SQLite3 Python ‘Incorrect number of bindings supplied. The current statement uses 1, … supplied’

Problem:

You are trying to run a simple SQL query with placeholders on a SQLite3 database, e.g.:

name = "mytable"
conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", name)

But you get an exception like this:

---------------------------------------------------------------------------
ProgrammingError                          Traceback (most recent call last)
<ipython-input-55-e385cf40fd72> in <module>
      1 name = "mytable"
----> 2 conn.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name=?;", name)

ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 7 supplied.

Solution:

You need to use a list as the second argument to conn.execute(...)!

Since you only gave the function a string, the string is being interpreted as list of characters.

In our example from above, you just need to wrap name in square brackets to read [name]:

name = "mytable"
conn.execute("SELECT sql FROM sqlite_master WHERE name=?;", [name])
Posted by Uli Köhler in Python, SQLite

How to list tables in SQLite3 database in Python

Also see How to list SQLite3 database tables on command line

You can use this snippet to list all the SQL tables in your SQLite 3.x database in Python:

def tables_in_sqlite_db(conn):
    cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table';")
    tables = [
        v[0] for v in cursor.fetchall()
        if v[0] != "sqlite_sequence"
    ]
    cursor.close()
    return tables

Usage example:

#!/usr/bin/env python3
import sqlite3
# Open database
conn = sqlite3.connect('/usr/share/command-not-found/commands.db')
# List tables
tables = tables_in_sqlite_db(conn)

# Your code goes here!
# Example:
print(tables) # prints ['commands', 'packages']

 

Posted by Uli Köhler in Databases, Python, SQLite

How to emulate the Enter key in Puppeteer

To emulate a keypress to the Enter key in Puppeteer, use

await page.keyboard.press("Enter");

The E needs to be uppercase for this to work!

Posted by Uli Köhler in Javascript, Puppeteer

How to emulate keyboard input in Puppeteer

To emulate the user typing something on the keyboard, use

await page.keyboard.type("the text");

This will type the text extremely fast with virtually no delay between the characters.

In order to simulate the finite typing speed of real users, use

await page.keyboard.type("the text", {delay: 100});

instead. The delay betwen characters in this example is 100 Milliseconds, i.e. the emulated user types 10 characters per second.

Posted by Uli Köhler in Javascript, NodeJS, Puppeteer

How to emulate TAB key press in Puppeteer

In order to emulate a tab key press in Puppeteer, use

await page.keyboard.press("Tab");

Full example:

// Minimal puppeteer example
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({defaultViewport: {width: 1920, height: 1080}});
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Press tab 10 times (effectively scrolls down on techoverflow.net)
  for (let i = 0; i < 10; i++) {
      await page.keyboard.press("Tab");
  }
  // Screenshot to verify result
  await page.screenshot({path: 'screenshot.png'});
  // Cleanup
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, Puppeteer

How to fix Puppeteer ‘Error: Unknown key: “tab”‘

Problem:

You want to emulate a tab key press using

await page.keyboard.press("tab");

but you get an error message like

(node:30594) UnhandledPromiseRejectionWarning: Error: Unknown key: "tab"
    at assert (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:270:11)
    at Keyboard._keyDescriptionForString (/home/uli/dev/myproject/node_modules/puppeteer/lib/Input.js:96:5)
    at Keyboard.down (/home/uli/dev/myproject/node_modules/puppeteer/lib/Input.js:44:30)
    at Keyboard.<anonymous> (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:112:23)
    at Keyboard.press (/home/uli/dev/myproject/node_modules/puppeteer/lib/Input.js:178:16)
    at Keyboard.<anonymous> (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:112:23)
    at /home/uli/dev/myproject/test.js:8:23
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
(node:30594) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:30594) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Solution:

You need to use Tab, not tab ! The T needs to be uppercase!

Use

await page.keyboard.press("Tab");

Full example:

// Minimal puppeteer example
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({defaultViewport: {width: 1920, height: 1080}});
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Press tab 10 times (effectively scrolls down on techoverflow.net)
  for (let i = 0; i < 10; i++) {
      await page.keyboard.press("Tab");
  }
  // Screenshot to verify result
  await page.screenshot({path: 'screenshot.png'});
  // Cleanup
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript

How to set <input> value in Puppeteer

Use this snippet to set the value of an HTML <input> element in Puppeteer:

const newInputValue = "test 123";
await page.evaluate(val => document.querySelector('.search-form-input').value = val, newInputValue);amp

Remember to replace '.search-form-input' by whatever CSS selector is suitable to select your <input>. Examples include 'input[name="username"]' or '.username > input'.

Full example:

// Minimal puppeteer example
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Set input value
  const newInputValue = "test 123";
  await page.evaluate(val => document.querySelector('.search-form-input').value = val, newInputValue);
  // Screenshot to verify result
  await page.screenshot({path: 'screenshot.png'});
  // Cleanup
  await browser.close();
})();

Note that this method will work for any simple <input>, however it might not work for some heavily Javascripted inputs which you can find on some modern websites.

Posted by Uli Köhler in Javascript, Puppeteer

How to save screenshot in Puppeteer as PNG?

You can take a screenshot in Puppeteer using

await page.screenshot({path: 'screenshot.png'});

The path is relative to the current working directory.

Want to have a screenshot in a size different to 800×600? See How to set screenshot size in Puppeteer?

Full example:

// Minimal puppeteer example
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Screenshot to verify result
  await page.screenshot({path: 'screenshot.png'});
  // Cleanup
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, NodeJS, Puppeteer

How to sleep in NodeJS using async/await

The easiest way to sleep using async/await in NodeJS is the sleep-promise package:

npm install --save sleep-promise

Using that package you can simply use await sleep(milliseconds) syntax like this:

const sleep = require('sleep-promise');

// In any async function:
await sleep(2000); // Wait 2000 ms

Note that this sleep() variant is fully asynchronous, IO and other asynchronous operations will still be able to continue in the background – sleep() will not block the NodeJS process.

Full example:

const sleep = require('sleep-promise');

(async () => {
    console.log("This prints immediately");
    await sleep(2000);
    console.log("This prints 2 seconds later");
})();

 

Posted by Uli Köhler in Javascript, NodeJS

NodeJS equivalent to Python’s time.sleep() using async/await

Install the sleep-promise package:

npm install --save sleep-promise

then you can use

const sleep = require('sleep-promise');

// In any async function:
await sleep(2000); // Wait 2000 ms

Full example:

const sleep = require('sleep-promise');

(async () => {
    console.log("This prints immediately");
    await sleep(2000);
    console.log("This prints 2 seconds later");
})();

 

Posted by Uli Köhler in Javascript, NodeJS

Minimal puppeteer response interception example

Using Python (pyppeteer)? Check out Pyppetteer minimal network response interception example

This example shows you how to intercept network responses in puppeteer.

Note: This intercepts the response, not the request! This means you can abort the request before it is actually sent to the server, but you can’t read the content of the response! See Minimal puppeteer request interception example for an example on how to intercept requests.

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  // Enable response interception
  page.on('response', async (response) => {
      console.info("URL", response.request().url());
      console.info("Method", response.request().method())
      console.info("Response headers", response.headers())
      console.info("Request headers", response.request().headers())
      // Use this to get the content as text
      const responseText = await response.text();
      // ... or as buffer (for binary data)
      const responseBuffer = await response.buffer();
      // ... or as JSON, if it's a JSON (else, this will throw!)
      const responseObj = await response.json();
  })
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Make a screenshot
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, Puppeteer

Minimal puppeteer request interception example

Using Python (pyppeteer)? Check out Pyppetteer minimal network request interception example

This example shows you how to intercept network requests in puppeteer:

Note: This intercepts the request, not the response! This means you can abort the request made, but you can’t read the content of the response! See Minimal puppeteer response interception example for an example on how to intercept responses.

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  // Enable request interception
  await page.setRequestInterception(true);
  page.on('request', async (request) => {
      console.info("URL", request.url());
      console.info("Method", request.method())
      console.info("Headers", request.headers())
      return request.continue(); // Allow request to continue
      // return request.abort(); // use this instead to abort the request!
  })
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Make a screenshot
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, Puppeteer

Javascript equivalent to Python’s re.findall()

The equivalent to this Python code which is using re.findall()

import re

hashtag_regex = r"(\B#\w\w+)"
hits = re.findall(hashtag_regex, "This is a string #with #hashtags")
print(hits) # prints ['#with', '#hashtags']

in Javascript is

const string = "This is a string #with #hashtags";
const re = /(\B#\w\w+)/g;
const hits = [];
// Iterate hits
let match = null;
do {
    match = re.exec(string);
    if(match) {
        hits.push(match[0]);
    }
} while (match);

console.log(hits); // Prints [ '#with', '#hashtags' ]

You need to assign your regular expression to a variable like re! If you use

match = /(\B#\w\w+)/g.exec(string); // WRONG ! Don't do this !

you will create an infinite loop which always generates the first hit in the string, if any!

Posted by Uli Köhler in Javascript

How to fix Puppeteer ‘Error: Protocol error (Emulation.setDeviceMetricsOverride): Invalid parameters width: integer value expected; height: integer value expected’

Problem:

You are trying to set the viewport size in Puppeteer using

const browser = await puppeteer.launch({
    defaultViewport: '1920x1080'
});

but you see an error message like

(node:15692) UnhandledPromiseRejectionWarning: Error: Protocol error (Emulation.setDeviceMetricsOverride): Invalid parameters width: integer value expected; height: integer value expected
    at /home/uli/dev/myproject/node_modules/puppeteer/lib/Connection.js:183:56
    at new Promise (<anonymous>)
    at CDPSession.send (/home/uli/dev/myproject/node_modules/puppeteer/lib/Connection.js:182:12)
    at EmulationManager.emulateViewport (/home/uli/dev/myproject/node_modules/puppeteer/lib/EmulationManager.js:41:20)
    at Page.setViewport (/home/uli/dev/myproject/node_modules/puppeteer/lib/Page.js:808:54)
    at Page.<anonymous> (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:112:23)
    at Function.create (/home/uli/dev/myproject/node_modules/puppeteer/lib/Page.js:49:18)
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
    at async Browser._createPageInContext (/home/uli/dev/myproject/node_modules/puppeteer/lib/Browser.js:177:18)
    at async /home/uli/dev/myproject/index.js:8:16
  -- ASYNC --
    at Target.<anonymous> (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:111:15)
    at Browser._createPageInContext (/home/uli/dev/myproject/node_modules/puppeteer/lib/Browser.js:177:31)
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
    at async /home/uli/dev/myproject/index.js:8:16
  -- ASYNC --
    at Browser.<anonymous> (/home/uli/dev/myproject/node_modules/puppeteer/lib/helper.js:111:15)
    at /home/uli/dev/myproject/index.js:8:30
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
(node:15692) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:15692) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Solution:

You need to use

{defaultViewport: {width: 1920, height: 1080}}

instead of

{defaultViewport: '1920x1080'}

Full example:

// Minimal puppeteer example
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch({
      defaultViewport: {width: 1920, height: 1080}
  });
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Make a screenshot
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, Puppeteer

How to set screenshot size in Puppeteer?

Problem:

You are trying to make a screenshot using Puppeteer like this:

await page.screenshot({path: 'screenshot.png'});

but the screenshot is always 800×600 pixels. How can you increase the size of the screenshot?

Solution:

You can’t set the size for the screenshot, you need to set the size for the viewport in puppeteer.launch:

const browser = await puppeteer.launch({
    defaultViewport: {width: 1920, height: 1080}
});

Full example to produce a 1920x1080 screenshot:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
      defaultViewport: {width: 1920, height: 1080}
  });
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  // Wait until page has loaded completely
  // Make a screenshot
  await page.screenshot({path: 'screenshot.png'});

  await browser.close();
})();

 

Posted by Uli Köhler in Javascript, Puppeteer

Puppeteer minimal example

You can use this example as a starting point for your puppeteer application.

// Minimal puppeteer example
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://techoverflow.net', {waitUntil: 'domcontentloaded'});
  //
  // YOUR CODE GOES HERE!
  //
  await browser.close();
})();

The screenshot is 800x600px by default and could look like this:

Posted by Uli Köhler in Javascript, NodeJS, Puppeteer