SF Bio, negativ marknadsföring och sökspindeljuridik

Kanske är det för att jag själv sysslat mycket med screenscraping och omstöpande av innehåll från andra webbplatser som jag tycker att SF Bio:s agerande enligt nedanstående är rent fantastiskt korkat — ännu mer så när det kommer från den enda sektor av filmbranschen som faktiskt i teorin kan erbjuda ett mervärde som inte kan kopieras digitalt.

”På SF medger man att biotider.se numera inte har möjlighet att automatiskt hämta information om var och när filmerna visas. Enligt informationschefen Thomas Runfors är nu de ”spindlar”, eller program, som biotider.se använt blockerade”

(SvD, läs även Bloggywood eller direkt från källan.)

Jag kände inte till biotider.se sedan tidigare (man kan väl anta att de fått rätt bra med uppmärksamhet nu i elfte timmen, då ovanstående just nu är förstanyhet på svd.se), men det verkar vara en schysst site – lagom web 2.0-ig ut med taggmoln och pastellfärger och användarinteraktion och annat bra som SF:s egen webbplats inte har. Att alienera sådana passionerade användare känns som grund för uppsägning för en marknadschef på 2000-talet.

Men marknadsföring är inte min grej, så vad vet jag. Dock är de juridiska aspekterna är ju intressanta. Jag kan se tre separata frågor.

1: Har SF någon ensamrätt över sina biotider? Jag tycker det känns lite tveksamt — nån vanlig upphovsrätt kan det inte vara frågan om (då såväl verkshöjd som originalitet saknas), men kanske s.k. databas- eller tabellskydd? Denna ensamrätt är en s.k. närstående rättighet, som regleras i samma lag som upphovsrätten, men lyder under andra villkor. Huvudregeln för att något ska skyddas på detta sätt är att att det ska vara antingen en samling av ett stort antal uppgifter, eller att samlingen ska vara resultatet av en stor investering. Både rättsläget och det aktuella fallet är alltför komplicerat för att jag ska våga mig på att reda ut huruvida någon ensamrätt föreligger för biotiderna, men det är i vart fall inte självklart. (Den intresserade läser lämpligtvis Fixtures mot Svenska Spel och fortsätter med Johan Axhamns examensuppsats)

2: Har SF möjlighet att spärra ut crawlers? Till att börja med kan man observera att SF inte har någon robots.txt-policy, vilket är lite märkligt eftersom de hänvisar till den från sinlänkpolicysida. Eftersom rättsläget kring rekvisiten för dataintrång är så pass luddigt i svensk rätt (vilket jag skrivit om tidigare) är det lite oklart vilken betydelse en sådan icke-maskinläsbar policy har, men vi får anta att biotider.se åtminstone numera är medvetna om att de inte har SF Bio:s tillåtelse att hämta datat (”bereder sig tillgång till en uppgift som är avsedd för automatiserad behandling”). Därmed kan det utgöra dataintrång att fortsätta.

3: Har SF möjlighet att förbjuda djuplänkar? (i betydelsen ”länk till en resurs annan än ”startsidan” på en webbplats.) Rent tekniskt har de möjligheten – sf.se har infört en referer-check genom vilken den som försöker följa en länk från biotider.se till SF:s bokningssida för en specifik film, plats och tid www.sf.se istället vidarebefordras till SF:s förstasida, och får välja film, plats och tid igen (och under processen exponeras för några reklambanners). Men kan SF på upphovsrättslig eller annan grund tvinga biotider.se att inte djuplänka? Rättsläget är inte solklart, men i tidigare diskussioner om länkning och svensk rätt har man främst riktat in sig på två fall:

  • inramade länkar, dvs när en frame-tagg i ett frameset på en första webbplats hänvisar till en annan webbplats så att det för användaren framstår som den externa webbbplatsens innehåll är en del av den första webbplatsens, eller
  • direktlänkar till ljud- eller bildfiler, som för användaren typiskt spelas upp utan att det tydligt framgår att innehållet kommer från en annan webbplats

Dessa skulle kunna falla in under beskrivningen av offentligt framförande, vilket är ett upphovsrättsligt förfogande. Men jag har svårt att se att en länkning från en sida till en annan sida, där det tydligt framgår att innehållet på den nya sidan kommer från en annan part, skulle kunna hindras på upphovsrättslig väg. Den kan förstås hindras på avtalsmässig väg, men nu har ju biotider.se och SF Bio knappast träffat något avtal.

Så möjligtvis finns det en (svag) juridisk grund för SF att hindra biotider.se att fortsätta sin verksamhet, även om det inte är den man hävdar i sina uttalanden. Klart är att man redan försökt hindra dem på teknisk väg åtskilliga gånger. Om SF lyckas blir förlorarna dels biotider.se, dels alla människor som trots att de blir utsatta för rent förolämpade pekpinnar envisas med att stödja filmbranschen. Men ser någon några vinnare?

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.

Juridiska vs tekniska lösningar på problem

Idag blev jag uppringd av en person från domstolsverket, som hade sett lagen.nu. Personen i fråga var dock kritisk till att jag länkar direkt till rättsfallen på deras site; genom mina länkar hade nämligen Google hittat till rättsfallen och indexerat dessa. Det ansåg man var dåligt, då vissa referat kan innhålla personuppgifter, och om dessa indexeras kan dessas personliga integritet kränkas. Detta är grundproblemet, vilket jag har viss förståelse för.

Domstolsverket hade ursprungligen tänkt att Google och andra sökmotorer inte skulle kunna indexera rättsfallen genom att man valt en relativt komplicerad weblösning för att göra dessa tillgängliga, men då jag lade in direktlänkar på lagen.nu brast den förutsättningen.

Fråga uppstod om huruvida jag inte borde ha kontaktat domstolsverket innan, och även om min hantering kunde tänkas bryta mot personuppgiftslagen. Vad gäller att be om tillstånd innan man länkar har jag alltid tyckt att det är fullständigt fel. Välkommen till webben, det är så här den funkar, liksom. Vad gäller PUL så är jag relativt säker på att min behandling, som enbart befattar sig med den data som finns i varje domsluts detaljvy, inte faller under dess bestämmelser, då personuppgifter enbart kan förekomma i referaten.

Jag har, från tid till annan, funderat på att även behandla/lägga upp referaten, men valt att inte göra det just på grund av hänsyn till personuppgiftslagen. En lösning på problemet skulle vara att skaffa ett utgivningsbevis för lagen.nu så att YGL blir tillämplig; då gäller (enkelt uttryckt) inte PUL. Av flera olika anledningar är dock inte det aktuellt i dagsläget. Men det är ett ämne för ett inlägg någon annan dag.

Sedan i eftermiddag har domstolsverket valt att lösa problemet genom att stoppa in en restriktiv robots.txt på sin tjänst. Detta gör att jag inte, enligt den sedvänja som gäller på internet, får screenscrape:a tjänsten. Vilket jag naturligtvis tycker är dumt, inte minst med avseende på offentlighetsprincipen, och vilket leder till att listorna med rättsfall under paragraferna på lagen.nu gradvis kommer bli mer och mer irrelevanta. Jag har mailat en förfrågan om huruvida domstolsverket kan göra ett undantag i denna policy för mig, men inte fått något slutgiltigt besked.

Trots att slutresultatet, åtminstone som det ser ut nu, går lagen.nu emot, så tycker jag ändå att domstolsverket har handlat ganska rätt. Visst borde de haft en robots.txt uppe sen dag ett, och visst borde de göra undantag för min webrobot, och kanske borde man fråga sig vad personuppgifterna har att göra i domslutsreferat som ska vara anonymiserade, men nu har de iaf löst ett tekniskt problem med en teknisk, snarare än en juridisk, åtgärd. Alla tjänar på att sådana här riktlinjer uttrycks med kod, inte författningar.

Har du olovligen berett dig tillgång till en upptagning för automatiserad databehandling idag?

Bruce Schneier länkar
till
en mycket intressant artikel
om vad begreppet ”Unauthorized access” betyder i datorsammanhang, i ett
rättsligt perspektiv, utgående från amerikansk rättspraxis och
-doktrin. Artikelförfattaren, Orin
S. Kerr
, kommer fram till att begrepp som ”access” och
”authorized” används som om deras mening vore otvetydig, när de i
själva verket är väldigt dåligt definerade. Artikeln är inte pinfärsk
(oktober 2003), men så vitt jag vet är de frågeställningar som tas upp
fortfarande aktuella. Det handlar helt enkelt om var gränsen för
brottet ”dataintrång” skall dras.

Svensk och amerikansk lagstiftning verkar vara ganska likartad här, i
det att det finns ett brott (dataintrång respektive ”unauthorized
access”) som har två rekvisit — i svensk lag ”att bereda sig tillgång
till upptagning för automatiserad databehandling”, samt att denna
handling skall vara ”otillåten” (BrB 4:9 c). Amerikansk lag
har de bägge rekvisiten i brottsbenämningen.

Jag har tidigare
intresserat mig
för den svenska motsvarigheten, och kom fram till
att framförallt ”olovligen” var ett väldigt suddigt begrepp. Kerr kommer även i sin artikel fram till att gränserna är suddiga och inte
har dragits konsekvent i praxis. Han förespråkar att
”kontraktsbaserade” överträdelser inte i sig ska bedömas som
”unauthorized”, utan att det ska krävas någon typ av kringående av en
teknisk accesskontroll:

This Article proposes that courts should reject contract-based
notions of authorization, and instead limit the scope of unauthorized
access statutes to cases involving the circumvention of code-based
restrictions. The fact that computer use violates a contractual restriction
should not turn that use into an unauthorized access. The bypassing
of a code-based restriction such as a password gate should be
required to trigger criminal liability, such that hacking into a computer
could be an unauthorized access, but violating Terms of Service would
not be.

En kontraktsbaserad överträdelse skulle här kunna vara att bryta mot
ett explicit eller implicit avtal (ett avtalsbrott kan dock
naturligtvis alltid angripas med civilrättsliga principer). Ett
explicit avtalsbrott skulle kunna vara att bryta mot en webtjänsts
användarvillkor, ett implicit avtalsbrott skulle kunna vara att
använda en annonsblockerare.

Den EG-konvention
om angrepp mot informationssystem
som Sverige har börjat
implementera iom Ds 2005:5 gav
utrymme för medlemsländerna att lagstifta om att det skulle krävas
kringgående av säkerhetsåtgärder för att rekvisitet ”olovligen”
skulle uppfyllas. Utredningen bakom Ds 2005:5 har valt att inte
utnyttja denna möjlighet, vilket jag tycker är synd. Det leder till,
som jag skrev i mitt tidigare
inlägg
, att många handlingar som har ett positivt värde för
samhället, kan betraktas som dataintrång.

Jag var på ett
föredrag
för ett tag sedan där Ds 2005:5 (och framförallt Ds 2005:6)
presenterades. Jag fick intrycket att målsättningen hade varit att
göra minsta möjliga ändring i de svenska lagarna för att kunna säga
att EG-konventionskraven är uppfyllda. Det är förmodligen därför man
inte gjorde något åt det hopplösa uttrycket ”bereder sig tillgång till
upptagning för automatisk databehandling” inte ändrats. Eller, fel av
mig, man föreslår faktiskt en ändring, till ”bereder sig tillgång till
en upptagning för automatiserad databehandling”…

Kerrs artikel ger en bra analys av varför en definition av
”unauthorized” som kan innefatta kontraktsbaserade överträdelser leder
till en oförutsägbar rättstillämpning. Jag hoppas att den svenska
lagstiftaren utnyttjar möjligheten till att tydliggöra begreppen
längre fram i lagstiftningsprocessen.

The legality of screenscraping

Niklas Lundblad directs
me
to a couple of interesting propositions about pending laws
regarding computer crime (one of them actually uses the phrase ”crimes
in cyberspace” — very 1995’ish retro). Both Ds 2005:5 and Ds 2005:6 are
intended to be the first steps in implementing recent EC legislation
(particularly ”Convention
on Cybercrime ETS no.:185
”) in swedish law.

Unfortunately, both documents are very thin when it comes to
defining what should be regarded as ”illegal access to information
systems”. Swedish law has not been well defined in this area
before, and I was hoping that maybe the lawmakers would take the
opportunity to clarify this.

The issue I’m mostly concerned with is screen
scraping
. I like screen scraping. I think screen scraping is
cool. I wrote my first screen scraping program the same week I got my
first job, almost ten years ago (it was a simple script to
automatically download the latest Dilbert cartoon and email it as an
attachment to myself).

Now, it’s easy to see why a content provider would be opposed to
screen scraping. When I got my Dilbert strip in my inbox, there was no
advertising attached to it, thus I was depriving Unitedmedia of ad
revenue.

Years later, I was involved in the XMLTV project as I was
playing around with a homebrew HTPC. For Swedish TV listings, there
was a simple program that would fetch TV listings from dagenstv.com and
re-format them into the XMLTV format. One day, their service started
to serve up a very hostile-worded text file when I ran this
program. Basically, dagenstv.com had changed their web server
configuration so that requests from a certain User-agent (our
screen scraper program), would get a stern warning that we were doing
illegal things and that our IP adress had been logged, or something
like that.

Now, were we doing something illegal? Keep in mind that each user
would run this program on his or hers individual computer; we never
redistributed the content. Wheter or not we could have done that
legally in Sweden is another question, one that maybe could be
answered by pondering URL 49
§
and related materials. It’s an interesting question in it’s own
right, just not the subject of today’s blog post.

Was the mere act of accessing the site with a different tool than
the site owner intended, thus gaining access to digital data in a
non-approved way, illegal? For me as a programmer, this feels like an
absurd question. I’m only sending humble GET
requests
, if the site owner doesn’t want me to have the
information, then don’t send it! But with my legal student-glasses on,
this could be considered as computer infringement, as per the wording
in BrB 4:9 c: ”Den som
[…] olovligen bereder sig tillgång till upptagning för automatisk
databehandling […]döms för dataintrång till böter eller fängelse i
högst två år.”
. (A rough translation would be ”Someone who gets
hold of a recording for automatic computer handling without permission
is to be sentenced for computer infringement to fine or prison for no
more than two years”
).

Dagenstv.com could be said to have given users with normal web
browsers implicit permission to access the data, but probably not to
us with our screen scraper. If we had asked the site owners, they
would very likely had said ”no”, and therefore, they could well argue
that we were getting hold of a ”recording” witout permission.

(As an aside: the use of ”recording” (”upptagning” in swedish) in
the quoted law text is interesting in it’s own right — the
legislation was originally written with telephone wiretapping, opening
of letters, and similar things in mind, then ”adapted” (used in the
loosest of senses) into the digital age.)

I would prefer that questions like these were solved by technical,
not legal, means. Dagenstv.com used one such mean (the User-agent
discrimination) to block our screen scraper. We could have changed our
program to masquerade as a normal Internet Explorer browser, but that
would only escalate into a pointless arms race. Someone wrote a
different script that fetched the data from another site instead, and
that was the end of it. Furthermore, if we had bypassed dagenstv.com’s
User-agent check, we would have essentially said ”Even though we’ve
been told in no uncertain terms that what we’re doing is not permitted
by the site owners, we’re choosing to ignore that and circumvent the
access control” — if we had done that, dagenstv.com would really be
right in saying we were getting hold of data without permission.

But there’s a lot to be said for screen scraping. lagen.nu could not exist without screen
scraping. A lot of really cool web services over the years have been
made possible by screen scraping. It has enabled loose
coupling
years before anyone had talked about web services. It’s
the basis for a lot of interesting research and data mining. And
sometimes it just enables plain cool stuff.

Furthermore, it would be wrong to assume that all content providers
are opposed to screen scraping. For example, what is the one thing
that distinguishes forward-thinking web companies? They provide API’s
to their services (Amazon,

Livejournal,
Yahoo, Google, Flickr), enabling
anyone to build cool applications on top of their data, just like we
wanted to build a cool HTPC application using data from
dagenstv.com. By providing API’s, smart web sites remove the need for
actual screen scraping (which, in all fairness, is a messy and seldom
very interesting technological challenge, and furthermore only a means
to an end), but enable and encourage the same kinds of applications.
These API’s (and the XML-RPC/SOAP-based underpinnings) did not emerge
from a vacuum. People have been screen-scraping Amazon.com for their
own little needs since it was launched. Smart service providers
realise that it’s better to work with all this creativity than against
it.

If web site providers choose to do what dagenstv.com did, then
fine. They’ve stated their intent, it’s their service, their rules,
they’re entitled to take their ball and go home. But before a site
owner puts such a block in place (which could also be done through a
robots.txt file), screen
scraping should in no way be considered unlawful computer
infringement.

It turns out that the EC
convention
that this new legislation is to implement provides for
these kinds of distinctions, under article 2 (my emphasis):

Article 2 – Illegal access

Each Party shall adopt such legislative and other measures as may be
necessary to establish as criminal offences under its domestic law,
when committed intentionally, the access to the whole or any part of a
computer system without right. A Party may require that the offence be
committed by infringing security measures
, with the intent of
obtaining computer data or other dishonest intent, or in relation to a
computer system that is connected to another computer system.

Knowingly circumventing a access control system by, for example,
changing the User-agent string, might be considered infringing
security measures (weak as they are), but an unassuming GET request
could, with this definition, never be considered illegal access. I
hope that Sweden takes this opportunity to better define what should
be considered illegal access.

Another aside: Since lot of my current activities, and thus my blog
writing, revolve around swedish law, it’s sometimes difficult to write
in English, as there are a lot of precise Swedish legal terms that I’m
not comfortable translating. For anyone versed in Swedish law, posts
about it in English is probably way harder to read. Furthermore, most
of these posts are probably of limited interest to non-swedes.

Therefore, I’m considering switching the language of this blog to
Swedish. If you don’t understand Swedish, but would like to continue
reading this blog, please say so in the comments. Thank you.

Part 3: Understanding what was fetched

(Earlier posts in this series: here
and here)

There are a lot of ways to extract data from a HTML file. You can
do simple string
searching
(by the way, why is the python documentation for
basic string objects hidden under the non-descript heading
”Sequence types”, and why is there no reference to that part of
the documentation from the separate
string module
, which hardly does anything?) and rexep
munging
, or you can use more
sophisticated
HTML
parsers
. Funnily enough, there are two of these in the Python
standard library, and both of them are callback based — why no
tree-based interface? If the HTML code is modern and well-formed,
you can even use a vast
array
of
XML tools (and if
it’s not, you can fix it with HTML Tidy).

I ended up using the BaseHTMLProcessor
approach from Dive
Into Python.
, which has a whole
chapter
devoted to the art of HTML parsing. Basically, you
subclass BaseHTMLProcessor, implementing callbacks for various
tags, which are called as these tags are encountered in the
document. Your class is responsible for keeping track of whatever
state (ie what depth you are in the document, what tags were
encountered before this one, and so on) that needs to be kept.

There are some things that are cumbersome with this approach. For
example, automatic HTML entity resolving would be good. The HTML
fragment
<h1>r&auml;ksm&ouml;rg&aring;s</h1gt;
represents a single header with the string ”räksmörgås” (a common
test phrase for
swedish programmers), and so it should only result in three
callbacks: start_h1, handle_data (which should
be called with the string ”räksmörgås”), and end_h1.

Instead, the following callbacks are called:

  • start_h1
  • handle_data (called with the string ‘R‘)
  • handle_entityref (called with the string ‘auml‘)
  • handle_data (called with the string ‘ksm‘)
  • handle_entityref (called with the string ‘ouml‘)

…you get the idea. There exists a
mapping
that helps with the entity resolving, but for the HTML
case, this could have been solved at a lower-level stage.

Still, for the parsing problems I have, the
callback-based/keep-your-own-goddam-state-approach works. Most of
the time I’m just concerned with finding the elements
in a table
, meaning I have to keep track of what cells I’ve
seen and when a new table row starts, things like that. As I go
along, build up a list of mappings or something similar, and then
just use that list once done. The calling code gets quite nice and
simple:

cl = SFSChangelogExtractor()
cl.feed(open("downloaded/lawinfo/%s.html" % self.basefile).read())
for c in cl.changelog:
    if c.item('SFS-nummer') == current_transitional_id: ...
  

(Note that the ‘c’ object here is not a standard dictionary, but a
mapping-ish object that also keeps track of the order keys have
been inserted. That’s why it’s c.item('SFS-nummer') and
not c['SFS-nummer']. That, and the fact that I was too
lazy to implement the special
methods
needed to do a proper Duck Typed
dictionary.)

The one exception is the problem of finding all the plaintext in a
law text like this
one
, but it’s even easier: Just increment a counter whenever a
<pre> tag is encountered, decrement it when seing
</pre>. In handle_entityref and handle_text, just
check if the counter is > 0 and if so, append the text to a StringIO
object.

Part 2: Fetching stuff from the web

(A continuation of the series started in this post)

Now, the first thing that needs to be done is to actually get
the text of the laws from the web. Before that can be done, a
list of available laws must be fetched. In Swedish law, most
laws have nice ID’s known as ”SFS-nummer”, usually on the form
”yyyy:nnn”, where yyyy is the year it was issued, and nnn is
incremented for each law passed that year. Some of the older
laws don’t strictly follow this convention, and can have ID’s
like ”1736:0123 2” or ”1844:50 s.2”.

To get a list of all laws passed between two years, one can use this form from
Regeringskansliets
Rättsdatabaser
. It uses the normal GET method, and so it’s
quite easy to construct a URL that will return all laws between,
say, 1600 and 1850 (linebreaks inserted for readability):

http://62.95.69.15/cgi-bin/thw?${HTML}=sfsr_lst&
${OOHTML}=sfsr_dok&${SNHTML}=sfsr_err&${MAXPAGE}=26&
${BASE}=SFSR&${FORD}=FIND&ÅR=FRÅN+1600&
ÅR=TILL+1850

To fetch this, I used urllib2. Now for a little aside rant: Why
are there two urllibs in the standard distribution? I understand
that basic urllib has a simple interface and urllib2 a more
complex, but would it be so hard to design a single module
that lets you do simple things easy, and progress onto hard
things? In the Perl world, you can start with LWP::Simple and
then go on to more advanced stuff, but with python it’s either
simple urllib requests with practially no control at all, or
urllib2 with it’s way-too-complex system of chained handlers. I
will return to this rant in a little bit, but for now let’s have
some useful content. This is the code used to fetch stuff:

url = "http://62.95.69.15/...ÅR=FRÅN+%s&ÅR=TILL+%s" % (1600,1850)
sock = urllib.urlopen(url)
html = sock.read()
  

So, as long as your needs are simple, like just wanting to do a
simple GET or POST, urllib and/or urllib2 will work. However, I
encountered a more complex scenario when I wanted to download
court verdicts from Domstolsväsendets
rättsinformation
: This is a web app that relies on HTTP
posts, HTTP redirects, session tracking cookies, frames,
javascript links and is, in general, incredibly fragile. The
slightest ”error” in what you send and the server answers with a
500 Server Error: java.lang.NullPointerException

The first problem was that the application requires cookie
support, which urllib2 doesn’t have (as it doesn’t have any
concept of state between requests). At first I thought I could fix
the cookie support by reading and setting headers, the way it was
done back in the day when men were men and knew the cookie
spec
by heart. Turns out the web service sets a cookie when
you issue a search request, but the answer from the search request
is a HTTP redirect. To get the resulting list of matches, you need
to present that same cookie that was set.

Now, let’s continue the rant: urllib2 blindly follows the
redirect, giving us no chance to set the Cookie header. From the
documentation, it appears that it should be possible to override
this behaviour by subclassing HTTPRedirectHandler and passing
the instance to build_opener, which creates a chain of instances
of BaseHandler or a subclassed class. Reading the documentation
for urllib2 makes me think that someones OO/design patterns
fetish was not kept properly in check. Anyway, I could not get
that to work.

Another thing that bugs me about urllib2 is that is has no
support for implementing Robots Exclusion Standard
(RES) support. Right now, neither Regeringskansliets databaser
or Domstolsväsendets rättsinformation has a
/robots.txt, but if they put one in tomorrow I think I
should respect it.

I did briefly use ClientCookie,
which is an add-on module for urllib2 that provides automatic
cookie support, and it did solve my first problem. Although I
did not try it, it can also be used to provide RES support,
proper Referer setting, and some other goodies. It seems that
at least the cookie handling functionality of ClientCookie has
been folded into urllib2 in Python 2.4, which is a good thing.

However, some time after I first got some code to work with the
site, they changed something around and made it even more
fragile. No matter what I did, I couldn’t get the site to
respond with anything other than a ”500 Server Error”,
even though I checked the client-server communication when using
IE (with the excellent Fiddler utility),
and replicated the behaviour down to the exact header level.

So, I remembered that Erik had told me about
the virtues of webscraping using IE
and COM automation
. Since I’m only running the code on
windows machines, giving up platform independence wasn’t that
big a deal, and the rich COM support in both Python and IE made
it quite easy (after installing pywin32 for
COM support). Here’s the basic code:

      from win32com.client import Dispatch
      ie = Dispatch("InternetExplorer.Application")
      ie.Visible = 1
      ie.Navigate("http://www.rattsinfosok.dom.se/lagrummet/index.jsp")
      while ie.Busy: sleep(1)
      ie.Document.frames(1).Document.forms(0).all.item("txtAvgDatumFran").value = startdate.strftime("%Y-%m-%d")
      ie.Document.frames(1).Document.forms(0).all.item("txtAvgDatumTill").value = "%s-12-31" % year
      ie.Document.frames(1).Document.forms(0).all.item("slctDomstol").value = "ALLAMYND"
      ie.Document.frames(1).Document.forms(0).all.item("buttonSok").click()
      while ie.Busy: sleep(1)
      html = ie.Document.frames(1).Document.body.outerHTML.encode('iso-8859-1')
  

With such a javascript- and browser behaviour dependent web app
such as this, you can really save yourself a whole lot of
trouble if your code can use that web browser instead of
trying to emulate that web browser. For one thing,
behaviour implemented in javascript (OnClick-handlers and the
like) is reproduced correctly without any extra work.

Well, that’s all for now about fetching stuff from the web. Next
installment will center around making sense of what we’ve just
fetched, i.e. parsing HTML and stuff.