!

Dette materialet blir ikke lenger vedlikeholdt. Du vil finne oppdatert materiale på siden: http://borres.hiof.no/wep/

Børre Stenseth
Python >Lese URL

Python og URL

Hva
Hvordan hente data fra en URL

Vi vil ofte av ulike grunner hente data fra en web adresse, en URL. Vi skal i denne modulen se på et par måter å gjøre dette på.

Web-snifferen er et godt verktøy for a analysere hva som går over en HTTP konversasjon: [1]

urllib

Den enkleste måten å gjøre dette på er å bruke urllib. Vi kan ganske enkelt skrive:

import urllib
theUrl='http://www.ia.hiof.no/~borres/ml/pyex/frej1.txt'
#Download a file and print it
try:
    f=urllib.urlopen(theUrl)
    S=f.read()
    f.close()
    print S
except:
    print 'cannot load'

Du kan kopiere koden og kjøre programmet fra din harddisk.

Det er 3 mulige utfall av dette:

  1. Alt går vel og programmet returnerer den ønskede tekstfila
  2. Adressen har feil format, dvs. Python oppdager at dette kan umulig være en URL. I så fall får vi en exception og får utskriften:'cannot load'
  3. Adressen har riktig format, men den oppgitte adressen finnes ikke. I så fall får vi tilbake en fil med angivelse av dette, typisk finnes ikke

Situasjonene 1 og 3 kan vi analysere ved å kopiere adressen inn i et browservindu.

Det er det siste utfallet, 3, som er problematisk. Vi må analysere resultatet for å se om dette er data av den typen vi er interessert i, som vi forventer, eller om det er en feilmeldingsside. Vi skal se nedenfor hvordan vi kan løse dette mer elegant med httplib.

Merk at urllib også på en enkel måte lar oss kopiere en fil fra en URL til en lokal fil:

import urllib
theUrl='http://www.ia.hiof.no/~borres/ml/pyex/frej1.txt'
theFile='c:\\temp\\frej1.txt'
#Download a file and save it locally
try:
    urllib.urlretrieve( theUrl,theFile) 
except:
    print 'cannot copy'

Problemstillingen med de tre mulige utfallene er den samme.

httplib

Med httlib kan vi skaffe oss mer kontroll. Her setter vi opp en forbindelse, connection, og vi kan kontrollere hva slags headerinformasjon vi får tilbake når vi forsøker å få kontakt. Blandt annet får vi opp feilen 404 når vi leter etter noe som ikke finnes. Vi forventer meldingen 200 når alt går bra.

"""
 read and print the content of an url
"""
import httplib
try:
    # set up a connection to host
    conn = httplib.HTTPConnection("www.ia.hiof.no")
    # send a get request for a certain file
    conn.request("GET", "/~borres/ml/pyex/frej1.txt")
    # read the response, header
    r1 = conn.getresponse()
    # expect 200 as a signal for all is well
    if r1.status!=200:
        print 'access problem'
        print r1.status, r1.reason    
    else:
        s=r1.read()
        print s
    conn.close()
except:
    print 'cannot connect'

Vi fanger opp situasjonen med ikke eksisterende server med en try - except. Nå ser vi at vi kan lese diagnosen på et leseforsøk uten å lese hele fila. Hodet, headeren, i forsøket på tilgang gir oss diagnosen. Kopier koden og forsøk å kjøre med å skrive inn en ikke-eksisterende server og alternativt med en ikke-eksistrende fil.

Vi kan også gjøre slik dersom vi skal sende med parametere til et cgi-skript og bruke POST:

import httplib, urllib
try:
    # prepare parameters
    params = urllib.urlencode({'navn': 'ole', 'adresse': 'mysen'})
    # prepare header
    headers = {"Content-type": "application/x-www-form-urlencoded",
               "Accept": "text/plain"}
    # connect
    conn = httplib.HTTPConnection("www.ia.hiof.no")
    conn.request("POST", "/~borres/cgi-bin/forms/std.py", params, headers)
    r1 = conn.getresponse()
    # ok ?
    if r1.status!=200:
        print 'access problem'
        print r1.status, r1.reason
    else:
        # get data
        data = r1.read()
        print data
    conn.close()
except:
    print 'cannot access data'

wikipedia

En kilde for data av ymse slag er wikipedia. Wikipedia ser ut til trenge en header med angivelse av "user-agent". Dette skriptet henter innholdet i en wikipedia side og printer det det finner

"""
 Reading a wikipedia file
"""
import httplib, urllib
try:
    # prepare header.
    # wikipedia demands a useragent, may be anything ?
    headers = {'User-Agent': "myself"}
    # connect
    conn = httplib.HTTPConnection("en.wikipedia.org")
    parameters=None
    conn.request("GET", "/wiki/Snow_leopard", parameters, headers)
    r1 = conn.getresponse()
    # ok ?
    if r1.status!=200:
        print 'access problem'
        print r1.status, r1.reason
    else:
        # get data as text
        data = r1.read()
        print data
    conn.close()
except:
    print 'cannot access data'

Videre er det slik at Wikipedia er XHTML strict og vi kan lage følgende:

"""
 Reading a wikipedia file
"""
import httplib, urllib
import sys
import xml.dom.minidom
try:
    # prepare header.
    # wikipedia demands a useragent, may be anything ?
    headers = {'User-Agent': "myself"}
    # connect
    conn = httplib.HTTPConnection("en.wikipedia.org")
    parameters=None
    conn.request("GET", "/wiki/Snow_leopard", parameters, headers)
    r1 = conn.getresponse()
    # ok ?
    if r1.status!=200:
        print 'access problem'
        print r1.status, r1.reason
        sys.exit(0)
    else:
        # get data as text
        data = r1.read()
        #print data
    conn.close()
except:
    print 'cannot access data'
    sys.exit(0)
    
# since wikipedia pages are wellformed we can build a dom
# from the data we found simply by adding a xml-header
page="""<?xml version="1.0" encoding="utf-8"?>
   %s
   """
try:
    dom=xml.dom.minidom.parseString(page%data)
except:
    res=sys.exc_info()
    print res[1]
    sys.exit(0)
    
# and we can use the dom or/and the tekst, depending on our purpose
paragraphs=dom.getElementsByTagName('p')
print 'Teksten er '+str(len(data))+' tegn lang'
print 'Det er '+str(len(paragraphs))+ ' paragrafer i teksten'
Referanser
  1. HTTP -sniffer Lingo4you - Sprachen Online Lernen web-sniffer.net/ 14-03-2010
Vedlikehold

B. Stenseth, september 2009

( Velkommen ) Python >Lese URL ( CGI )