Python og URL
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:
- Alt går vel og programmet returnerer den ønskede tekstfila
- 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'
- 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'