local stuff for local (gov) people

playing with playwright with my chum claude

not sure if this is ✨vibe coding✨ or just standard assisted coding - i work step by step with Claude, i know enough Python to understand and tweak the output, i’m just a lazy bum when it comes to churning out this kind of stuff

the problem

part of a data analysis / reconciliation project i am working on automating currently involves someone manually downloading CSV files from a supplier website. they have to download multiple files with specific parameters that must not overlap. they have to split the downloads because the files are so large it sometimes crashes their browser. not ideal.

the supplier has just told me they were mistaken when they said they could set up an automated export, their ICT wont allow them to use SFTP or automate sending by email 🥴 even though its our data. also not ideal.

can we automate it?

i’ve heard about playwright but never used it. i dont really have time to learn it from scratch as i have a meeting in 2 hours where i’m going to be asked for an update on this project.

while we arrange the WTF 🤨 conversation with the supplier account manager, lets have a punt at automating it with claude

Kidlin’s Law

i recently came across Kidlin’s Law - in essence - “If you can write down the problem clearly, you’re halfway to solving it”.

i think this is extra important when it comes to working with LLMs. if you can’t articulate what you want clearly, you’re going to struggle.

edited to add this excellent quote from the article those HN comments relate to:

The skill isn't syntax anymore. It's not algorithms. It's not even system design, really. It's something like "coherent desire" or "precise imagination" or "structured wishing."

for me step 1 is usually to describe what i want as best i can, then ask claude to ask me what he needs to know to get on with the job

when i say as best i can - a good starting point is to act like you are explaining the problem to a brand new, junior member of staff. try and cover:

it needs to download the entire preceeding month based on the current date. so if the script is run on any day in july 2025 it will download 01/06/25 to 30/06/25. date inputs are in DD/MM/YYYY format.
the downloaded file should be renamed with the dates so a june download should become: transaction_history_2025_06.csv

depending on the complexity of the ask I might ask claude (possibly with extended thinking enabled) to draw up a plan and a spec that details the system design, key considerations, and usage workflow, without any code. then we refine this before starting work on the actual thing.

claude came back with a nice list of questions about the site i was working with, login method, download format, a click by click description of the export process etc

i gave him my answers and he drew up a nice little script using playwright! it read my login credentials from my .env file, and had place holders for all the selectors in my login and import process. so i needed to work through them one by one and fill in the correct values

for each element that the script needed to interact with i would need to provide the identifier.

i did this by running through the process with developer tools > elements open. for each thing i would use the inspect element mode (the pointy arrow in a box button at the top left of the screen) to click on the item, which would take me to its details. i couldn’t use right click > inspect element on most of the hover over menus, but if i hovered to open them then enabled the picker i could pinpoint the right bit.

right clicking on each lets you copy it, i find the info easier to look at in notepad.

first off i tried using the ID for everything:

# Click 2 - open main menu
        await page.click('#ext-comp-1005') 

but i found when running the script some of the IDs are dynamic, so i switched to using the class identifiers for those steps instead:

# Click 6 - generate report
        await page.click('.x-btn-text.x-grid-icon-64')  

if you are stuck you can just paste the copied element into your AI and ask for advice 😄

after some twiddling about i had a script that ran! and downloaded a file! 🤩

i then went back and added dynamic date filtering and renaming of the file to match the date filter! 👏

claude did a good job at adding the new elements, but made some basic mistakes like fluffing the package imports and replacing some of my identifiers with the original placeholders. and putting the timeout wait in the wrong place lol. but it was still a lot quicker for me to correct those than to write the thing from scratch!

for this I used claude sonnet 4 in the browser chat. i keep meaning to set up claude code at home but haven't got round to it 🤡

meeting time

nobody really cared about my script because they were too busy being angry that the supplier said no to SFTP 🤷‍♀️ lol

it now runs on our visualcron server which uploads the file to OneLake for further processing. we’ll battle away with the supplier about the SFTP thing. but for now i dont have to do a manual thing, and i learnt a new thing. 🙂

the whole thing from vague idea to working process took about 1.5 hours

bonus free learning

dont try to eat hummus and type and the same time. it wont be ok.

#build stuff #computer friend