2012-07-15 21 views
20

Ich möchte alle iframe von einer Webseite erhalten.Liste der Wörterbücher Python erstellen

Code:

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) 

Ergebnis 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'} 

Ergebnis 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'}] 

Warum ist der Wert des Inhalts nicht wahr? Es wird angenommen, dass es derselbe ist wie der Wert, wenn ich print(info).

Antwort

43

Sie sind nicht ein separates Wörterbuch für jeden iframe erstellen, können Sie einfach immer und immer wieder das gleiche Wörterbuch ändern, und Sie halten das Hinzufügen zusätzlicher Verweise auf dieses Wörterbuch in Ihrer Liste.

Denken Sie daran, wenn Sie etwas wie content.append(info) machen, machen Sie keine Kopie der Daten, Sie fügen einfach einen Verweis auf die Daten hinzu.

Sie müssen für jeden Iframe ein neues Wörterbuch erstellen.

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

Noch besser, Sie müssen nicht zuerst ein leeres Wörterbuch erstellen. schafft es einfach alles auf einmal:

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

Es gibt auch andere Möglichkeiten, dies, wie Iterieren über eine Liste von Attributen oder mit Liste oder Wörterbuch Comprehensions zu erreichen, aber es ist schwer, auf der Klarheit des obigen Codes zu verbessern .

+0

Dank für kurze Erklärung, dies ist mein erster Code mit Python: D. Danke auch für die schnelle Antwort – l1th1um

2

info ist ein Zeiger auf ein Wörterbuch - Sie fügen den gleichen Zeiger auf Ihre Liste contact.

Insert info = {} in die Schleife, und es sollte das Problem lösen: halten

... 
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

Sie haben das Objekt Python list falsch verstanden. Es ähnelt einem C pointer-array. Es "kopiert" nicht wirklich das Objekt, das Sie an es anhängen. Stattdessen wird nur ein "Zeiger" auf das Objekt gespeichert.

den folgenden Code Versuchen:

>>> 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}] 

Warum ist print(dlist) nicht das gleiche wie print(d)?

Der folgende Code zeigt Ihnen den Grund:

>>> 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 

So können Sie alle sehen die Elemente in der dlist zeigt tatsächlich auf den gleichen dict Objekt.

Die wirkliche Antwort auf diese Frage wird sein, die "Kopie" des Zielelements anzufügen, indem d.copy() verwendet wird.

>>> 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}] 

Versuchen Sie, den id() Trick können Sie die Listenelemente weisen tatsächlich auf ganz andere Objekte sehen.

>>> 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

Also ... befürworten Sie, dass der Benutzer die '.copy()' Methode verwendet, anstatt nur ein neues Wörterbuch bei jeder Iteration zu erstellen? Ich denke, das ist falsch in diesem speziellen Fall. –

+0

In vielen Fällen können Sie nur einen Teil des Elements ändern, im Hinblick auf Leistung und Präzision bevorzuge ich '.copy()'. Im Bereich Bildung bietet '.copy()' auch ein klareres Konzept. – Wang

+2

Ich denke, '.copy()' macht nur Sinn, wenn Sie tatsächlich etwas kopieren möchten. Obwohl Sie sich einig sind, dass Sie in einigen Fällen nur einen Teil eines Elements ändern möchten, denke ich, dass das OP im Falle dieser speziellen Frage eindeutig beabsichtigt, ein neues Wörterbuch für jeden Iframe zu erstellen, anstatt es zu kopieren und zu modifizieren.

3

Wenn Sie eine Zeile wollen:

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