Browse Source

create zoopla-manchester.org file.

master
Craig Oates 2 months ago
parent
commit
5facabddf8
  1. 257
      zoopla-manchester.org

257
zoopla-manchester.org

@ -0,0 +1,257 @@
#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline author:t
#+options: broken-links:nil c:nil creator:nil d:(not "LOGBOOK") date:t e:t
#+options: email:nil expand-links:t f:t inline:t num:t p:nil pri:nil prop:nil
#+options: stat:t tags:t tasks:t tex:t timestamp:t title:t toc:t todo:t |:t
#+title: Zoopla Manchester
#+date: \today
#+author: Craig Oates
#+email: craig@craigoates.net
#+language: en
#+select_tags: export
#+exclude_tags: noexport
#+creator: Emacs 29.1.90 (Org mode 9.7-pre)
#+cite_export:
* Setup Common Lisp Environment
I’ve copied the following code block over from other files. Run it if this is
your first file open in the session.
#+begin_src lisp :session :results silent
(ql:quickload :com.inuoe.jzon) ; JSON parser.
(ql:quickload :dexador) ; HTTP requests.
(ql:quickload :plump) ; HTML/XML parser.
(ql:quickload :lquery) ; HTML/DOM manipulation.
(ql:quickload :lparallel) ; Parallel programming.
(ql:quickload :cl-ppcre) ; RegEx. library.
(ql:quickload :plot/vega) ; Vega plotting library.
(ql:quickload :lisp-stat) ; Stat's library.
(ql:quickload :data-frame) ; Data frame library eqv. to Python's Numpy.
(ql:quickload :str) ; String library, expands on 'string' library.
#+end_src
* Gather Zoopla Rent Data (Manually)
- [[https://www.zoopla.co.uk/][Zoopla]]
The site produced a single page so I didn't feel the need to scrap the data. I
just saved the page into =raw-data/external/2024-03-18-zoopla-rent-manc/=. The
data is the actual HTML and CSS, so the files will not be committed to the
repository, to match the established behaviour of the other sites I've already
looked at.
The filters I used:
- Date: 2024-03-18
- Location: Manchester City Centre, Greater Manchester
- Radius: 'This area only'
- Price Range: £400–£1,300 pcm
- Only monthly rents listed
* Clean Up and Parse Data
Going to separate the listings out into their own files, to match the
established behaviour with other sites I've looked at.
#+begin_src shell :results silent
mkdir raw-data/external/2024-03-18-zoopla-rent-manc-listings/
#+end_src
[[file:./raw-data/external/2024-03-18-zoopla-rent-manc-listings/]]
#+begin_src lisp :results silent
(let ((counter 0))
(loop for file-path
in (directory #P"raw-data/external/2024-03-18-zoopla-rent-manc/*.html")
do (with-open-file (in-stream file-path)
(let* ((doc (plump:parse in-stream))
;; .listing-info
(listings (lquery:$ doc ".dkr2t82" (serialize))))
(loop for item across listings
do (let ((out-path
(merge-pathnames
#P"raw-data/external/2024-03-18-zoopla-rent-manc-listings/"
(format nil "listing-~a.html" (write-to-string counter)))))
(with-open-file (out-stream
out-path
:direction :output
:if-exists :supersede)
(format out-stream "~a~%" item))
(incf counter)))))))
#+end_src
#+begin_src shell :results output
COUNT=$(ls -1 "raw-data/external/2024-03-18-zoopla-rent-manc-listings/" | wc -l)
echo "There are $COUNT files in the directory."
#+end_src
#+RESULTS:
: There are 14 files in the directory.
There are some listings which are student-only. Unfortunately, there doesn't
seem to be a filter for removing student-only listings. So, I'll need to remove
them manually at little later down the line. The total amount of listing is
small enough for it to not be a problem.
** Create CSV of Listings
#+begin_src lisp :results output raw
(let ((row-id 0)
(out-file #P"working-data/2024-03-18-zoopla-manc.csv"))
(with-open-file (out-stream
out-file
:direction :output
:if-exists :supersede)
(format out-stream "ROW-ID,RENT,LOCATION,URL,DESCRIPTION~%")
(loop for input
in (directory #P"raw-data/external/2024-03-18-zoopla-rent-manc-listings/*.html")
do (with-open-file (in-stream input)
(let* ((doc (plump:parse in-stream))
(price (lquery:$ doc "._64if862._194zg6t6" (text)))
(description (lquery:$ doc ".m6hnz63._194zg6t9" (text)))
;; e.g. Transform '£1,250 per month' to '1250'.
(cleaned-price
(first
(cl-ppcre:all-matches-as-strings
"\\d+"
(cl-ppcre:regex-replace-all
"[\\s\\n]+"
(format nil "~s" (str:replace-all "," "" (aref price 0)))
" "))))
(location (lquery:$ doc "address" (text)))
(link (lquery:$ doc "a" (attr :href))))
(format out-stream "~d,~d,~a,~a,~a~%"
row-id
cleaned-price
(str:replace-all "," " " (aref location 0))
(cl-ppcre:regex-replace "\\?search.*" (aref link 0) "")
(str:replace-all "," " " (aref description 0)))))
(incf row-id)))
(format t "[[file:./~a]]" out-file))
#+end_src
#+RESULTS:
[[file:./working-data/2024-03-18-zoopla-manc.csv]]
*I've manually removed the student-only listing, since creating the CSV file.*
File is left with 5 listings.
* Explore CSV Data for Zoopla (2024-03-18)
#+begin_src lisp :session
(lisp-stat:defdf *zoop-man*
(lisp-stat:read-csv #P"working-data/2024-03-18-zoopla-manc.csv"))
#+end_src
#+RESULTS:
: #<DATA-FRAME:DATA-FRAME (5 observations of 5 variables)>
The total amount of listings is tiny, so I can list them out here.
#+begin_src lisp :session :results output drawer
(lisp-stat:print-markdown *zoop-man*)
#+end_src
#+RESULTS:
:results:
| ROW-ID | RENT | LOCATION | URL | DESCRIPTION |
|--------+------+--------------------------------------------------------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------|
| 2 | 1150 | Arches Whitworth Street West Manchester M1 | https://www.zoopla.co.uk/to-rent/details/65630906/ | **3 month agreements only - available 23rd March** A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ... |
| 3 | 1150 | Water Street Manchester M3 | https://www.zoopla.co.uk/to-rent/details/66713818/ | 1-6 months Tenancy bills included no couples due to regulations**Perfect for Contractors & Work Teams****Perfect for Business ... |
| 5 | 1250 | Arches Whitworth Street West Manchester M1 | https://www.zoopla.co.uk/to-rent/details/66338812/ | *3 month agreements only - available 23rd March* A true Manchester gem minutes from the Northern Quarter Canal Street and Piccadilly. This is ... |
| 8 | 1050 | Little Lever Street Manchester Greater Manchester M1 | https://www.zoopla.co.uk/to-rent/details/65042494/ | ** available from 19/04/2024 ** ** all bills inclusive in rent ** Reeds Rains are delighted to market this fantastic furnished studio apartment ... |
| 11 | 1089 | Cross Street Manchester M2 | https://www.zoopla.co.uk/to-rent/details/66673111/ | Listing code 692841. Our contemporary studio apartments at 25 Cross Street are thoughtfully designed to a high standard.Featuring a comfy double ... |
:end:
#+begin_src lisp :session :results file
(vega:defplot zoopla-monthly-manc
`(:title "Rent Rates for Manchester on Zoople (18/03/2024)"
:width 600
:height 600
:data ,*zoop-man*
:layer #((:mark (:type :bar)
:encoding (:x (:field :row-id :title "Assigned Id." :type :nominal :axis ("labelAngle" 0))
:y (:field :rent :title "Monthly Rent with Bills Inc. (£)" :type :quantitative)
:tooltip (:field :rent)))
(:mark (:type rule :color "darkorange" :size 3)
:encoding (:y (:field :rent :type :quantitative :aggregate :average)
:tooltip (:field :rent :type :quantitative :aggregate :average))))))
(vega:write-html zoopla-monthly-manc "renders/2024-03-18-zoopla-rent-manc.html")
#+end_src
#+RESULTS:
[[file:renders/2024-03-18-zoopla-rent-manc.html]]
#+begin_src shell :results silent
mv ~/Downloads/visualization.png ./renders/2024-03-18-zoopla-rent-manc.png
#+end_src
[[file:./renders/2024-03-18-zoopla-rent-manc.png]]
#+begin_src lisp :session :results output code raw
(format t "- Mean Rent: £ ~a~%" (float (lisp-stat:mean *zoop-man*:rent)))
(format t "- Min. Rent: £ ~d~%" (reduce #'min *zoop-man*:rent))
(format t "- Max. Rent: £ ~d" (reduce #'max *zoop-man*:rent))
#+end_src
#+RESULTS:
- Mean Rent: £ 1137.8
- Min. Rent: £ 1050
- Max. Rent: £ 1250
#+begin_src calc :results output
1137.8 * 12
#+end_src
#+RESULTS:
: 13653.6
* Summary of Zoopla
Based on the average rent for Zoopla, I would need to make around £14,000/yr to
cover my living costs. This doesn't include travel, food, clothing, socialising
or Income Tax Payments.
Most listing were aimed at students and the number of listings was tiny,
especially when compared to [[file:./spare-room-manchester.org][Spareroom]] and [[file:./open-rent-manchester.org][Open Rent]].
To get an idea of what I need for ’survival mode’, I'll add £5,000 onto the
total above and apply the usual calculations, established in the other files.
#+begin_src calc :results output
13653.6 + 5000
#+end_src
#+RESULTS:
: 18653.6
Using £18,653.6 as the starting point (see [[file:./uk-wage-tax.org][UK Wage and Tax Rated]],
#+begin_src lisp :results output raw
(let* ((earning-target 18653.6)
(p-allow 12570)
(taxable-income (- earning-target p-allow))
(tax-to-pay (* taxable-income 0.2))
(total (- earning-target tax-to-pay)))
(format t "- Annual Target Salary: £~a~%" earning-target)
(format t "- Part of Salary which is Taxable: £~a~%" taxable-income)
(format t "- Tax to Pay: £~a~%" tax-to-pay)
(format t "- Salary After Tax: £~a~%" total))
#+end_src
#+RESULTS:
- Annual Target Salary: £18653.6
- Part of Salary which is Taxable: £6083.5996
- Tax to Pay: £1216.72
- Salary After Tax: £17436.879
| Time Span | Value After Tax (£) | Mean Rent (£) |
|-----------------------+---------------------+---------------|
| Annually | 17436.88 | 1137.8 |
| Monthly (Before Rent) | 1453.0733 | |
| Monthly (After Rent) | 315.2733 | |
| Weekly (After Rent) | 78.818325 | |
| Daily (After Rent) | 11.259761 | |
#+TBLFM: @3$2=@-1/12::@4$2=@-1-@-2$+1::@5$2=@-1/4::@6$2=@-1/7
So, the spending limit is £11.26/day.
Loading…
Cancel
Save