Tilbage til oversigten
Christian Nielsen

Sådan kørte jeg en scraper til en klient uden at betale for en eneste server

Sådan kørte jeg en scraper til en klient uden at betale for en eneste server

Sådan kørte jeg en scraper til en klient uden at betale for en eneste server

Nogle gange er den rigtige infrastruktur den, der koster ingenting.

En af mine klienter arbejder som freelance-censor – den person, der sidder med til praktiske prøver og godkender om kandidaterne består. Platformen han bruger til at finde nye prøver poster opslag i løbet af dagen. Ingen notifikationer, ingen alarmer. Bare en tabel, der opdaterer sig, når der kommer noget nyt.

Han sad og checkede siden manuelt. Mellem møder, mellem andet arbejde – bare ramte F5 og scannede ned ad listen. Jeg spurgte ham, hvor længe han havde gjort det. “Et stykke tid,” sagde han.

Opsætningen: GitHub Actions + Gmail + Go + SQLite

Inden jeg rørte noget som helst, tjekkede jeg platformens vilkår og betingelser. Ingen politik mod automatiseret adgang, ingen robots.txt-restriktioner på de relevante stier. Vi var good to go.

Løsningen var ikke kompliceret i konceptet – poll siden hvert 30. minut i arbejdstiden, sammenlign hvad der er der nu mod hvad der var der sidst, og send ham en mail hvis der er noget nyt.

Den lidt interessante del var infrastrukturbeslutningen. Jeg gad ikke sætte en VPS eller en cloud-funktion op til noget så letvægtigt. GitHub Actions’ gratisplan giver 2.000 CI/CD-minutter om måneden på private repos. At køre noget hvert 30. minut fra 07:00 til 17:00 på hverdage bruger måske 300 af dem. Resten sidder bare der.

Så hele løsningen kører som et GitHub Actions-workflow på et cron-skema:

on:
  schedule:
    - cron: '0,30 7-17 * * 1-5'

Binæren kompilerer, kører og afslutter. Ingen server, ingen daemon, intet at passe.

Login-håndtering: CSRF-tokens og krypterede sessioner

Platformen kræver login for at se opslag, hvilket betød det skulle håndteres ordentligt frem for at lave et fuldt login ved hver kørsel.

Binæren gør hvad en browser ville gøre: henter login-siden, trækker det dynamiske CSRF-token ud (et skjult 32-tegns felt, der roterer ved hver request), og POSTer credentials sammen med det. Efter et vellykket login serialiseres session-cookies som JSON, krypteres med AES-256-GCM og gemmes i en SQLite-database, der ligger i repo’et.

Ved næste kørsel dekrypterer den de cookies, loader dem ind i HTTP-klienten og laver en hurtig test-request for at se om sessionen stadig lever. Hvis den gør, intet login nødvendigt. I praksis sker et fuldt re-login én gang hvert par dage.

Scraping og deduplicering

Med en aktiv session POSTer binæren en filtreret søgning efter den specifikke type opslag klienten er interesseret i. Opslag er fordelt over flere sider, så den paginerer igennem flere offsets for at sikre intet bliver misset. goquery parser hvert HTML-tabel og trækker titel, dato, sted og tilmeldingslink ud fra hver række.

Hvert fundet link tjekkes mod en seen-tabel i den samme SQLite-database. Nye rykkes over i en afsendsliste og skrives straks tilbage til databasen, så de ikke dukker op igen. Databasen passer sin egen størrelse – vokser den over 190 MB sletter den de ældste poster og kører VACUUM for at frigøre pladsen. Ingen manuel vedligeholdelse.

E-mail-alarmen

Når der er nye opslag, bygger binæren en styled HTML-mail – ét kort per opslag med titel, dato, sted og en direkte tilmeldingsknap – og sender den via Gmail SMTP med en App Password. Flere modtagere er understøttet.

Klientens eneste opgave var at tilføje afsenderadressen til sine betroede afsendere, så mails ikke havner i spam. Det var hele opsætningen fra hans side.

Resultatet

Den kører stille, koster ingenting, og han har ikke behøvet at tænke på den siden.

Det jeg godt kunne lide ved den her var, at den rigtige løsning også var den kedelige. Ingen cloud-funktioner, ingen managed services, ingen månedlig faktura. Bare en kompileret Go-binary der kører på en gratis CI-runner og skriver til en SQLite-fil.


Har du noget lignende – en proces du gentager manuelt fordi platformen ikke sender notifikationer – er du velkommen til at skrive til mig.

– Christian