2012-07-15 16 views
20

Voglio ottenere tutto il iframe da una pagina web.Crea elenco del dizionario Python

Codice:

site = "http://" + url 
f = urllib2.urlopen(site) 
web_content = f.read() 

soup = BeautifulSoup(web_content) 
info = {} 
content = [] 
for iframe in soup.find_all('iframe'): 
    info['src'] = iframe.get('src') 
    info['height'] = iframe.get('height') 
    info['width'] = iframe.get('width') 
    content.append(info) 
    print(info)  

pprint(content) 

risultato di print(info):

{'src': u'abc.com', 'width': u'0', 'height': u'0'} 
{'src': u'xyz.com', 'width': u'0', 'height': u'0'} 
{'src': u'http://www.detik.com', 'width': u'1000', 'height': u'600'} 

risultato di pprint(content):

[{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}, 
{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}, 
{'height': u'600', 'src': u'http://www.detik.com', 'width': u'1000'}] 

Perché il valore del contenuto scorretto? Supponiamo che sia uguale al valore quando I print(info).

risposta

43

Non sta creando un dizionario separato per ogni iframe, basta tenere modificando lo stesso dizionario più e più volte, e continuare ad aggiungere ulteriore riferimenti a quel dizionario nella tua lista.

Ricorda, quando fai qualcosa come content.append(info), non stai facendo una copia dei dati, stai semplicemente aggiungendo un riferimento ai dati.

È necessario creare un nuovo dizionario per ciascun iframe.

for iframe in soup.find_all('iframe'): 
    info = {} 
    ... 

Ancora meglio, non è necessario creare prima un dizionario vuoto. Basta creare tutto in una volta:

for iframe in soup.find_all('iframe'): 
    info = { 
     "src": iframe.get('src'), 
     "height": iframe.get('height'), 
     "width": iframe.get('width'), 
    } 
    content.append(info) 

Ci sono altri modi per ottenere questo, come ad esempio l'iterazione su un elenco di attributi, o utilizzando l'elenco o comprensioni del dizionario, ma è difficile da migliorare la chiarezza del codice di cui sopra .

+0

Grazie per breve spiegazione, questo è il mio primo codice utilizzando python: D. Grazie anche per la risposta rapida – l1th1um

2

info è un puntatore a un dizionario: si continua ad aggiungere lo stesso puntatore all'elenco contact.

Inserire info = {} nel ciclo e dovrebbe risolvere il problema:

... 
content = [] 
for iframe in soup.find_all('iframe'): 
    info = {} 
    info['src'] = iframe.get('src') 
    info['height'] = iframe.get('height') 
    info['width'] = iframe.get('width') 
... 
25

Hai frainteso l'oggetto Python list. È simile a un C pointer-array. In realtà non "copia" l'oggetto che gli si aggiunge. Invece, memorizza semplicemente un "puntatore" su quell'oggetto.

provare il seguente codice:

>>> d={} 
>>> dlist=[] 
>>> for i in xrange(0,3): 
    d['data']=i 
    dlist.append(d) 
    print(d) 

{'data': 0} 
{'data': 1} 
{'data': 2} 
>>> print(dlist) 
[{'data': 2}, {'data': 2}, {'data': 2}] 

Allora, perché è print(dlist) non è la stessa print(d)?

Il codice seguente mostra il motivo:

>>> for i in dlist: 
    print "the list item point to object:", id(i) 

the list item point to object: 47472232 
the list item point to object: 47472232 
the list item point to object: 47472232 

modo da poter vedere tutti gli elementi della dlist è in realtà che puntano allo stesso dict oggetto.

La vera risposta a questa domanda sarà aggiungere la "copia" dell'oggetto di destinazione, utilizzando d.copy().

>>> dlist=[] 
>>> for i in xrange(0,3): 
    d['data']=i 
    dlist.append(d.copy()) 
    print(d) 

{'data': 0} 
{'data': 1} 
{'data': 2} 
>>> print dlist 
[{'data': 0}, {'data': 1}, {'data': 2}] 

provare il id() trucco, è possibile vedere le voci di elenco in realtà puntano a oggetti completamente diversi.

>>> for i in dlist: 
    print "the list item points to object:", id(i) 

the list item points to object: 33861576 
the list item points to object: 47472520 
the list item points to object: 47458120 
+1

Quindi ... stai sostenendo che l'utente usa il metodo '.copy()' invece di creare un nuovo dizionario su ogni iterazione? Penso che sia sbagliato in questo caso specifico. –

+0

In molti casi, è possibile modificare solo una parte dell'elemento, nell'aspetto delle prestazioni e della concisione, preferisco '.copy()'. Nell'aspetto dell'educazione, '.copy()' fornisce anche un concetto più chiaro. – Wang

+2

Penso che '.copy()' abbia senso solo quando si vuole copiare qualcosa. Pur essendo d'accordo sul fatto che in alcuni casi si desideri modificare solo una parte di un elemento, nel caso di questa particolare domanda penso che l'OP intendesse chiaramente creare un nuovo dizionario per ogni iframe, piuttosto che copiare e modificare.

3

Se si vuole una linea:

list_of_dict = [{} for i in range(list_len)]