Cachning och throttling för webspindlar i python

Om du inte ägnar dig åt att programmera webspindlar i Python är dagens post förmodligen inte av så stort intresse.

Men: Jag har ägnat långfredagen åt att bland annat putsa på några utökningar till urllib2. För länge sedan skrev jag något i stil med att
urllib2 var alldeles för komplext, men jag lutar nu åt att det ”bara” är underdokumenterat.

Jag behövde ett sätt att från ett pythonprogram hämta websidor utan att hämta samma sida två gånger i onödan. Jag ville dessutom att förfrågningarna inte skulle ske allt för tätt inpå varandra — jag ville med andra ord ha en cache och en throttling-mekanism. Det visar sig att urllib2’s modell med kedjade handlers som anropas efter varandra lät mig göra det hela på ett mycket smidigt sätt.

Här är resultatet: StandaloneRobot.py. Testkoden i slutet förklarar hur det funkar; en anropare kan observera hur cache/throttling har använts genom att titta efter x-cache och x-throttling-headers i resultatet.

Lagringsmekanismen för cachen är inte den smartaste, men den funkar. Den implementerar inte en ”riktig” cache såsom en sådan ska funka enligt HTTP/1.1, utan har en GET-förfrågan till en viss URL skickats så får alla efterföljande förfrågningar till samma URL det cacheade svaret — tills man raderar cachen.

En lägesrapport

Jag är inte död, men en lite högre belastning har gjort att energin
att blogga inte funnits. Lite spridda upplysningar om vad som hänt sen
den 17:e november. Jag:

Macfilsystem och unicode

Jag är, om inte en varm förespråkare för svenska språket, så åtminstone militant förkämpe för våra svenska tecken. Att se ett filnamn som raksmorgas.txt eller en URL i stil med http://foo.com/overgangsbestammelser gör ont i mig. Så när jag började med etikettexperimentet ville jag naturligtvis bevara svenska tecken både utåt och inuti systemet.

Just nu ser det faktiskt inte så bra ut utåt, då det står http://lagen.nu/etikett/s%C3%A4rskiljningsf%C3%B6rm%C3%A5ga i webläsarens URL-rad när det borde stå http://lagen.nu/etikett/särskiljningsförmåga — en bieffekt av spännande UTF-8-problem på Win32-versionen av Apache, vilket jag kanske berättar mer om nån annan gång — men inåt är det ganska fint.

Eftersom allting som kan vara en statisk fil är det på lagen.nu så sparas naturligvis ovanstående websida som
index/tags/särskiljningsförmåga.html i filsystemet. Filsystemet är, i det här fallet, ett NTFS-filsystem. Jag gör hela genereringen av alla statiska sidor på en windowsmaskin, nämligen, eftersom det är det enda fartmonstret jag har hemma (och det tar ändå flera timmar). Sen, när allt är klart, rsync‘ar jag över allt till den Mac OS X-maskin som driftar själva lagen.nu.

Och det var här nånstans problemen började. Att överföra ”särskiljningsförmåga.html” från Windows till MacOS X över SMB (den ”vanliga” fildelningen) gick utmärkt, men med rsync fick jag det obegripliga felmeddelandet ”invalid argument”.

Det visade sig att Mac OS X-filsystemet internt lagrar filnamn i ”Normalization form D” — en unicodevariant på att representera tecken genom, att i fallet för bokstaven ‘ä’, först ange ‘a’ följt av U+0308 aka COMBINING DIARESIS, dvs två fristående prickar, avsedda att kombineras med föregående tecken. Det är inte nödvändigtvis så tokigt — jag matar in ‘ü’ på den här datorn genom att först trycka på ”två fristående prickar”-knappen, sedan ‘u’, en snarlik tankeprocess. Men det verkar lite bakvänt att lagra saker på det viset i filsystemet. Det verkar riktigt bakvänt att inte ens tillåta API-anropen för att skapa filer att använda alla giltiga unicodetecken. Och det verkar urbota tokbakvänt att skeppa MacOS X med en rsync som inte kompenserar för det här — jag vet inte om rsync-protokollet stödjer en angivelse av teckenuppsättning för filnamn, men i brist på annat borde man väl anta UTF-8 eller åtminstone Latin-1. Jag menar, det funkar finfint med den samba som levereras med systemet, som sköter den vanliga fildelningen.

Men så är det, så vad gör man? Man skriver ett litet fulhack som transformerar
särskiljningsförmåga.html till särskiljningsförmaÌŠga.html (den UTF-8-kodade representationen av det Normalization Form D-omvandlade filnamnet, sett genom Latin-1-glasögon), rsyncar, problem solved!

Svenska tecken funkar utmärkt på MacOS X vanligtvis — ända tills man gör något som inte riktigt förutsetts. Exempel: skapa en fil räksmörgås.txt i Finder, byt sen till Terminalen och prova följande:

[staffan@minimac tmp]$ ls r*.txt
-rwxr--r--  1 staffan  staffan  10  4 Sep 17:28 ra??ksmo??rga??s.txt*

Ett utmärkt exempel på en läckande abstraktion.

Imorgon ska jag tala om hur man inte ska designa sina RSS-feeds. Jepp, även de måste designas, men kanske inte på det sätt man först tänker.

flac2mp3.py

I have a medium-sized CD collection (around 500 or so albums), but
like most geeks I never actually fetch the disks and put them in my
CD/DVD player anymore. Instead, I rip them to some digital format and
listen to them on my computer, my portable MP3 player, or my showcenter. I’ve
been listening to music this way ever since I first discovered CD Copy back in -97 or so, and ripped
my entire collection.

Back then, disk space was expensive and MP3 encoders were less
stellar than they are now,
and so after a couple of years my collection of 128 Kbit/s rips
started to sound bad compared to what was practical in 2000. Another
round of ripping, this time to 192 Kbit/s, which was fine for a while,
until I got a portable MP3 player that didn’t have a lot of storage
(256 MB), but a nice WMA encoder. WMA in a portable player sound
perfectly OK at 64-80 Kbit/s, but not if you convert from a MP3
(because of the lossy nature of both MP3 and WMA, a MP3->WMA
conversion will be lossy2).

So, if I was to re-rip my 500 CD’s for the third time, I wanted to
do it right. I could rip them to plain WAV files, and then write small
scripts that would convert them to my preferred format for portable
devices, but WAV has two problems: Firstly, the files get huge, and
secondly, it has no good standard for metadata (like song, artist,
album etc).

Enter FLAC. Open source
implementation, lossless decent compression and excellent metadata
capabilities. So, when I’m re-ripping now I use EAC with the configuration
given at this
page
(scroll down a bit for the FLAC configuration), and hopefully
I should never have to do it again after this.

So, now I have a tree full of albums in FLAC format. To make things
extra pretty, I’ve even used Album
Cover Art Downloader
to create those folder.jpg files
that gets used by Windows XP’s Thumbnail view. Only one problem,
though — neither my Showcenter nor my portable player can play
FLAC. I neeede a way of batch converting my FLAC collection to MP3
and/or WMA.

Well, I haven’t solved it for WMA yet, but with this script you
can convert such a tree to MP3 files, as long as you have python, lame
and the command-line FLAC encoder. It’s written for windows, but
should run under any Unix variant without too much trouble, I hope. It
is written with the assumption that your folder structure is only one
level deep, ie directories should be named ”Johnny Cash – At Folsom
Prison”, not with subdirectories like ”Johnny Cash/At Folsom
Prison”. Since I rarely have more than three albums with any one
artist, I find the ”Artist/Album” convention mostly annoying.

Configure the upper-case variables, start a command prompt, cd’ to
the root of your FLAC tree, run the script and then be patient (for
me, the conversion takes well over 24 hours, and I have a relatively
zippy computer).

No license, do whatever you feel like with it (but do let me know
if you find it useful!)