Gå til innhold

Anbefalte innlegg

Jeg skal lage et script som henter ned ting automatiks fra en plass på nettet. Til dette skal jeg bruke urlretrieve i modulen urllib. I listen med filer som skal lastes ned, er det en del ikke-eksisterende filer(men jeg vet ikke hvilke av dem det er). Om jeg prøver å laste ned en ikke-eksisterende fil, får jeg lastet ned en html-fil(404 melding). Er det noen måte å sjekke om en fil eksisterer(utenom å analysere innholdet). Kan man i det hele tatt skille mellom en "virkelig" fil og en 404 melding?

Lenke til kommentar
Videoannonse
Annonse
Jeg skal lage et script som henter ned ting automatiks fra en plass på nettet. Til dette skal jeg bruke urlretrieve i modulen urllib. I listen med filer som skal lastes ned, er det en del ikke-eksisterende filer(men jeg vet ikke hvilke av dem det er). Om jeg prøver å laste ned en ikke-eksisterende fil, får jeg lastet ned en html-fil(404 melding). Er det noen måte å sjekke om en fil eksisterer(utenom å analysere innholdet). Kan man i det hele tatt skille mellom en "virkelig" fil og en 404 melding?

 

Spørsmålet er jo hva webserveren gir deg tilbake. Hvis den gir 200 Ok og en feilmelding, så er det ikke enkelt å se på status-kodene. Hvis den faktisk gir 404, så er det lettere å sjekke.

 

Vanligvis pleier jo alle slike feilmeldingssider å være like, så lett nok å sjekke om du fikk en feilmelding.

 

Selv pleier jeg ofte å bruke curl (via pycurl) til slike ting. Kan være ett godt alternativ.

Lenke til kommentar
  • 2 uker senere...

Sjekk HTTP spesifikasjonen og dokumentasjonen til urllib.

Ved en glance så kan du bruke URLopener sin FancyURLopener for å håndtere errors i urllib. Alternativt kan du bruke urllib2 som har enda mer error håndtering.

 

En måte med URLopener:

 

In [1]: import urllib, sys
In [2]: try:
       furl = urllib.URLopener({})
       o = furl.open("http://www.uio.no/noexist")
       o.read()
except IOError, errstr:
       print errstr
  ...:     
  ...:     
('http error', 404, 'Not Found', <httplib.HTTPMessage instance at 0x847a58c>)

 

For å lese HTTP headere eksplisitt må du nok bruke httplib.

Lenke til kommentar

Dette er vel ein grei måte å gjere det på:

 

import httplib
def is_valid_url(host, path):
c = httplib.HTTPConnection(host)
c.request('GET', path)
response = c.getresponse()
return response.status != 404

>>> is_valid_url('henriklied.no', '/sakdnkasd.html')
False
>>> is_valid_url('henriklied.no', '/')
True

 

Og forresten, JeffK: start.no/tingsomikkeeksiterer gir tilbake "404 Not Found" viss du inspiserer HTTP-responsen. :)

Endret av Henrik Lied
Lenke til kommentar
  • 2 uker senere...

Takk for alle svar! Jeg endte opp med å prioritere kompakt script fremfor å optimalisere antall overførte bytes. Her er det endelige scriptet, om noen er interessert:

 

#!/usr/bin/env python
from datetime import date
import hashlib
import urllib
import os
try:
import wx
hasWx = True
except:
hasWx = False

baseurl = 'http://www.start.no/tegneserier/m/mstriper/' 

redownload = False
verbose	= True
duplikates = False
makealbum = True

strips = {} # List of md5 sums for files you already have

nonex = urllib.urlopen(baseurl + "nonexistingfile").read()
nonexmd5 = hashlib.md5(nonex).hexdigest()

start = date(2004,10,25).toordinal()
stop  = date.today().toordinal()

numdays = stop - start

def mksubdir(direc):
direcs = map(lambda s: s + '/', direc.split('/'))
for i in range(0, len(direcs)):
	if not os.path.exists(''.join(direcs[0:(i+1)])):
		os.mkdir(''.join(direcs[0:(i+1)]))
if hasWx:
app = wx.PySimpleApp()
prd = wx.ProgressDialog("Fremgang", "Fremgang", numdays,
	style = wx.PD_AUTO_HIDE 
	| wx.PD_ELAPSED_TIME
	| wx.PD_ESTIMATED_TIME)

for i in range(start, stop+1):
if hasWx:
	prd.Update(i - start)

normdate = date.fromordinal(i)	
if i < date(2005,1,16).toordinal(): 
	stripfile = normdate.strftime('%d%m%Y')
else: 
	stripfile = 'm'+normdate.isoformat().replace('-','') 
stripfile += '.gif'

if verbose: print "Laster ned stripe %i av %i(%s)... " % (i-start+1, numdays,stripfile),

folder = "striper/" + str(normdate.year) + "/" + ("%02i" % normdate.month) + "/"
if (not redownload) and os.path.exists(folder + stripfile):
	if verbose: print "eksisterer allerede"
	temp = open(folder + stripfile, "rb")
	md5sum = hashlib.md5(temp.read()).hexdigest()
	temp.close()
	if not md5sum in strips:
		strips[md5sum] = [(date.fromordinal(i), folder + stripfile)]
	elif duplikates:
		strips[md5sum].append((date.fromordinal(i), folder + stripfile))
	continue

strip = urllib.urlopen(baseurl + stripfile).read()

md5sum = hashlib.md5(strip).hexdigest()

if md5sum == nonexmd5:
	if verbose: print 'eksisterer ikke'
	continue

if md5sum in strips:
	if duplikates:
		strips[md5sum].append((date.fromordinal(i), folder + stripfile))
	else:
		if verbose: print 'duplikat'
		continue
else:
	strips[md5sum] = [(date.fromordinal(i), folder + stripfile)]

mksubdir(folder)
open(folder + stripfile,"wb").write(strip)
if verbose: print "ferdig"

if makealbum:
x = 0
s = strips.values()
s.sort()
album = '<html><body><center><h1>"Daglige" M-striper</h1></center>\n'
for i in s:
	x += 1
	album += str(x) + "/" + str(len(s)) + ": " + i[0][0].strftime('%d.%m.%Y') + ':<br><img src="' + i[0][1] + '"><br>\n'
album += '</body></html>'
f = open('album.html','w')
f.write(album)
f.close()

 

Endret av JeffK
Lenke til kommentar

JeffK: Ved å laste BODY til kvar enkelt side bruker du jo langt meir tid på å hente stripene. Her er ein liten fix:

 

#!/usr/bin/env python
from datetime import date
import hashlib
import urllib
import httplib

import os
try:
import wx
hasWx = True
except:
hasWx = False

def is_valid_url(host, path):
c = httplib.HTTPConnection(host)
c.request('GET', path)
response = c.getresponse()
return response.status != 404

baseurl = '/tegneserier/m/mstriper/'
host = 'start.no'

redownload = False
verbose	= True
duplikates = False
makealbum = True

strips = {} # List of md5 sums for files you already have

nonex = urllib.urlopen(baseurl + "nonexistingfile").read()
nonexmd5 = hashlib.md5(nonex).hexdigest()

start = date(2004,10,25).toordinal()
stop  = date.today().toordinal()

numdays = stop - start

def mksubdir(direc):
direcs = map(lambda s: s + '/', direc.split('/'))
for i in range(0, len(direcs)):
	if not os.path.exists(''.join(direcs[0:(i+1)])):
		os.mkdir(''.join(direcs[0:(i+1)]))
if hasWx:
app = wx.PySimpleApp()
prd = wx.ProgressDialog("Fremgang", "Fremgang", numdays,
	style = wx.PD_AUTO_HIDE
	| wx.PD_ELAPSED_TIME
	| wx.PD_ESTIMATED_TIME)

for i in range(start, stop+1):
if hasWx:
	prd.Update(i - start)

normdate = date.fromordinal(i)	
if i < date(2005,1,16).toordinal():
	stripfile = normdate.strftime('%d%m%Y')
else:
	stripfile = 'm'+normdate.isoformat().replace('-','')
stripfile += '.gif'

if verbose: print "Laster ned stripe %i av %i(%s)... " % (i-start+1, numdays,stripfile),

folder = "striper/" + str(normdate.year) + "/" + ("%02i" % normdate.month) + "/"
if (not redownload) and os.path.exists(folder + stripfile):
	if verbose: print "eksisterer allerede"
	temp = open(folder + stripfile, "rb")
	md5sum = hashlib.md5(temp.read()).hexdigest()
	temp.close()
	if not md5sum in strips:
		strips[md5sum] = [(date.fromordinal(i), folder + stripfile)]
	elif duplikates:
		strips[md5sum].append((date.fromordinal(i), folder + stripfile))
	continue

if is_valid_url(host, "%s%s" % (baseurl, stripfile)):
	strip = urllib.urlopen("%s%s%s" % (host, baseurl, stripfile)).read()
	md5sum = hashlib.md5(strip).hexdigest()


	if md5sum in strips:
		if duplikates:
			strips[md5sum].append((date.fromordinal(i), folder + stripfile))
		else:
			if verbose: print 'duplikat'
			continue
	else:
		strips[md5sum] = [(date.fromordinal(i), folder + stripfile)]

	mksubdir(folder)
	open(folder + stripfile,"wb").write(strip)
	if verbose: print "ferdig"

if makealbum:
x = 0
s = strips.values()
s.sort()
album = '<html><body><center><h1>"Daglige" M-striper</h1></center>\n'
for i in s:
	x += 1
	album += str(x) + "/" + str(len(s)) + ": " + i[0][0].strftime('%d.%m.%Y') + ':<br><img src="' + i[0][1] + '"><br>\n'
album += '</body></html>'
f = open('album.html','w')
f.write(album)
f.close()

Endret av Henrik Lied
Lenke til kommentar

Ditt skript ble med min tilkobling ca 20-25% tregere. Det er sikkert fordi man må koble til to ganger for hver gyldige url(bodyen til 404-siden er jo ikke så stor). Man kunne sikkert ha tjent noe på å bare fortsette på denne eksisterende tilkoblingen.

Lenke til kommentar
  • 3 uker senere...

302 betyr at filen er funnet, men at den egentlig er flyttet til en annen URI. Den nye URI'en sendes med i HTTP Location-feltet, anbefaler at du så prøver denne. Jeg regner med at man har HTTP Keep-alive satt, så da taper du ikke noe særlig ytelse på dette. Bruker du rette så URI'er (etter å hente dem fra 302'en) vil du få en 200 (OK) når fila finnes, og 404 (Not Found) når den er borte.

 

Jeg er dog ikke helt sikker, ettersom du sier at man får en 302 (Found) selv om fila ikke finnes, noe som høres veldig merkelig ut.

 

Å sjekke response.status != 404 er forøvrig en dårlig løsning, da det finnes mange andre feilkilder (403 Forbidden, 500 Internal Server Error, f.eks. for å nevne noen av de mest berømte). Du bør heller sjekke om status == 200, og evt. 302 og 307 som spesialtilfeller.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...