When we last left off, we had our AddressCreator partially working. It makes a request to fakena.me and receives a response. Now we need to actually use that response.

The address is embedded in the HTML that we’re getting back. Here’s an example:

<!DOCTYPE html>
<html lang="en">
  <head>
	<!-- SNIP -->
  </head>

  <body>

    <!-- Wrap all page content here -->

    <div id="wrap">

      <!-- Begin page content -->
      <div class="container" style="text-align:center;">
	<h1>Random Valid US Address</h1><br><br><br><br>
<p style="font-size:20pt;"><strong>939 S Kingsley Dr<br>Los Angeles, CA 90006-1208</strong></p><br><br><a href="https://www.google.com/maps/place/939 S Kingsley Dr,Los Angeles,CA" target="_blank">Go to a Google Map of this location</a><br><br><br><p style="text-align:center;"><a class="btn btn-info btn-lg" href="/" alt="Go back to the fakena.me home page">Go Back to the fakena.me Home Page</a></p>
<br><br>
	<!-- SNIP -->
  </body>
</htm>l

As you can see, the data we want is buried in there. There are several ways we could extract the info we need and break it apart, but I opted for a combination of techniques, only one of which is regex! 😃

Step 1: Parsing with Cheerio

The address is buried inside a <strong> tag in the response. We could probably regex that out easily enough, but wouldn’t it be nice if we could select the target element? Maybe using jQuery syntax? Well, that’s exactly what cheerio let’s us do!

Cheerio, in its own words, is a: "fast, flexible & lean implementation of core jQuery designed specifically for the server."

It will let us do things like this:

const cheerio = require('cheerio')
const $ = cheerio.load('<h2 class="title">Hello world</h2>')
 
$('h2.title').text('Hello there!')
$('h2').addClass('welcome')
 
$.html()
//=> <html><head></head><body><h2 class="title welcome">Hello there!</h2></body></html> 

Let’s go ahead and install it now:

npm i cheerio --save

We can hook this up to request-response quite easily by specifying a transform function. Over in addressCreator.js, let’s do the following:

const rp = require('request-promise-native');
//Add the new require for cheerio...
const cheerio = require('cheerio');

class AddressCreator {

    static getRandomAddress() {
        
        const requestOptions = {
            uri: 'https://fakena.me/random-real-address/',
            //Set our transform function!
            transform: html => cheerio.load(html)
        }

        return rp(requestOptions);
    }
}

module.exports = AddressCreator;

Now when our request returns, we’re going to get back a cheerio selector, which we can use to parse the response HTML. Let’s grab that <strong> tag:

return rp(requestOptions).then($ => {
    const rawAddress = $('strong').html();

    //...
});

That will give us the raw address that looks like "8602 Flint Ave<br>Lubbock, TX 79423-3014". Now we just need to break that apart with some good, ole’ fashioned regex!

    const regex = /(\d+ [\w ]+)\<br\>([\w ]+), ([A-Za-z]{2}) (\d{5}-\d{4})/g;

    const match = regex.exec(rawAddress);

    if (match === null || match.length !== 5) {
        console.error('Unable to parse the result!');
        return;
    }

Putting it all together, getRandomAddress now looks like this:

    static getRandomAddress() {
        
        const requestOptions = {
            uri: 'https://fakena.me/random-real-address/',
            transform: html => cheerio.load(html)
        }

        return rp(requestOptions).then($ => {
            const rawAddress = $('strong').html();

            const regex = /(\d+ [\w ]+)\<br\>([\w ]+), ([A-Za-z]{2}) (\d{5}-\d{4})/g;

            const match = regex.exec(rawAddress);

            if (match === null || match.length !== 5) {
                console.error('Unable to parse the result!');
                return;
            }
            
            return {
                street: match[1],
                city: match[2],
                state: match[3],
                zip: match[4]
            };
        });
    }

Now our app gives the expected output when we execute it:

> node index.js
180 Lakeview Dr
Aurora IL 60506-4438

That takes care of retrieving a random address, but the title of this series isn’t "A Simple Node App to Generate Random Addresses," it’s "A Simple Node App to Generate Random Addresses and Geocode Them!" We still have some work to do!

In the next post, we’ll see how we can take the address we’ve retrieved and augment it with lat/long information. Stay tuned!