Note: Expect a part two on this post.
I know a guy, and that guy is looking for an apartment. It turns out that apartments are going really fast and inventory is low — maybe you knew this, but it was news to me. Just about as soon as they become available, they are gone. I suggested that I might be able to lend a hand… maybe, who knows. This is not because I know someone in apartments, but rather that if there is a way to use PowerShell here, then there is a good chance I can help. He got lucky and I learned something new.
I started by going to the apartment website where he was interested and found a page that listed each apartment model and whether or not they had any availability. It was a floor plan page. I was not expecting much honestly, but I used the built-in Web Developer Tools in my browser and viewed the page source, and found some exciting news (for me and PowerShell, at least). It was enough good news that I am able to write about this whole experience.
While empty here, this data structure caught my eye. The output I had hoped to gather, was in JSON format; that was huge! Best I can tell, it is generated by a JavaScript file, which then embeds the JSON in the HTML that makes up the webpage. That is not overly important, however, but look at this structure; it is magnificent.
floorplans: [ {... }, {... }, {... }, {... }, {... }, {... } ], propertyID: 60484,
Inside the floor plans JSON array ([]
) are six objects, each in their own set of curly braces. Inside each of those, was a plethora of information regarding each floor plan. These properties included things like Model, Sq.Ft., Beds, Baths, etc. Let’s start by taking a look at the Watch-Apartment
PowerShell function I wrote. Just a note, but in order to make this work for yourself, you will need to edit the path in the $ContentPath
variable.
function Watch-Apartment { $Uri = 'https://theplaceatcreekside.securecafe.com/onlineleasing/the-place-at-creekside/floorplans' $WebRequestContent = (Invoke-WebRequest -Uri $Uri).Content $ContentPath = 'C:\users\tommymaynard\Documents\tommymaynard.com\Apartment Hunting\WebpageContents.txt' Set-Content -Path $ContentPath -Value $WebRequestContent $File = Get-Content -Path $ContentPath $Pattern = "floorplans:(.*?)propertyID:" $ParsedPage = [regex]::Match($File,$Pattern).Groups[1].Value $ParsedPage = $ParsedPage.Trim(); $ParsedPage = $ParsedPage.TrimEnd(',') $JsonDocument = ConvertFrom-Json -InputObject $ParsedPage $JsonDocument | Select-Object -Property @{Name='Available';Expression={if ($_.isFullyOccupied -eq 0) {"Yes ($($_.availableCount))"} else {'No'}}}, @{Name='Model';Expression={$_.name}}, @{Name='Sq.Ft.';Expression={$_.sqft}}, @{Name='Beds';Expression={$_.beds}}, @{Name='Baths';Expression={$_.baths}} | Format-Table -AutoSize } Watch-Apartment
We will discuss the above function using its line numbers:
Line 1: Declares/creates the Watch-Apartment
function.
Line 2: Stores the site’s URI inside the $Uri
variable.
Line 3: Invokes an Invoke-WebRequest
command using the URI and stores the Contents (as in the Contents
property) inside the $WebRequestContent
variable.
Line 4: Creates the ContentPath
variable to hold a path to a text file that will be created in the next line/command.
Line 5: Takes the content from the webpage and writes it to a text file.
Writing to a file was not a requirement, however, it was my first choice for whatever reason and so I went with it, and then stayed with it.
Line 7: Read in the contents from the file and store them in the $File
variable.
Line 8: Create a Regex pattern to allow us to collect all the content between the word “floorplans:” and “propertyID:”.
Line 9: Parse out the data we want and store it in the $ParsedPage
variable.
Line 10: Trim off the white space from the beginning and end of the JSON string, and then trim off the trailing comma at the end of the JSON string.
Line 12: Assign the $JsonDocument
variable the value assigned to the $ParsedPage
variable after it has been converted from JSON by CovertFrom-Json
.
Lines 13 – 19: Use Select-Object
to select and modify our desired properties.
In the final command, we determine which floor plan is available, how many apartments there are, which model it is, how many square feet that model has, and how many bedrooms and bathrooms it has. Each line/property includes a calculated property and often, just to modify the case of the text.
I edited the friend’s PowerShell profile script and added this function. Not only is the function added to the PowerShell session by the profile script, but it also invokes the function, too. Open PowerShell, and just about instantly know whether anything is available or not.
These were the results the first time it ran back on my machine.
It was a good thing that the Available
property included both the isFullyOccupied
(“Yes” versus “No”) and the availableCount
(# of apartments) information. Take a look at the next image to see why.
In the above image, it still says, “Yes,” but the count is zero. Apparently, my decision to include both values was the right choice, as this information is not all updated at the same time.
Later that same day, it cleared up.
Now, he waits, as my work is done.
Note: As stated at the top of this post, expect a part two. There is more than one apartment complex now.