2012-07-15 55 views
20

我想從一個網頁得到所有的iframe創建字典的名單Python的

代碼:結果print(info)

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) 

:中pprint(content)

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

結果:

[{'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'}] 

爲什麼是內容的價值不正確的?假設它與I print(info)的值相同。

回答

43

沒有創建一個單獨的字典每個iframe中,只需保持一遍又一遍修改同一字典,您不斷添加額外的在您的列表中引用該字典。

記住,當你這樣做content.append(info),你是不是使數據的副本,你只是追加到數據的引用。

你需要爲每個iframe的一個新的字典。

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

更好的是,您不需要先創建空字典。只要創建,一次就全部:

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

還有其他的方法來做到這一點,如循環訪問屬性,或者使用列表或字典內涵的名單,但很難在上面的代碼的清晰度改善。

+0

感謝簡短的解釋,這是使用python我的第一個代碼:d。感謝您的快速響應 – l1th1um 2012-07-15 17:01:51

2

info是一個指向字典 - 你保持添加相同的指針列表contact

插入info = {}進入循環,它應該解決的問題:

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

你誤會了Python list對象。它類似於C pointer-array。它實際上並不是「複製」你追加的對象。相反,它只是存儲一個指向該對象的「指針」。

試試下面的代碼:

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

那麼爲什麼print(dlist)不一樣print(d)

下面的代碼顯示你的原因:

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

所以,你可以看到在dlist所有項目實際上是指向同一個對象dict

真正回答這個問題將是追加目標項目的「複製」,使用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}] 

嘗試id()技巧,你可以看到列表中的項目實際指向完全不同的對象。

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

因此......您主張用戶使用'.copy()'方法而不是在每次迭代時創建一個新字典?我認爲在這個具體案例中這是錯誤的。 – 2012-07-15 14:52:11

+0

在許多情況下,你只能改變項目的一部分,在性能和簡潔方面,我更喜歡'.copy()'。在教育方面,'.copy()'也提供了一個更清晰的概念。 – Wang 2012-07-15 15:04:38

+2

我認爲'.copy()'只有當你真的想要複製某些東西時纔有意義。雖然同意在某些情況下,您可能只想更改某個項目的一部分,但在這個特定問題的情況下,我認爲OP顯然打算爲每個iframe創建一個新字典,而不是複製和修改。 2012-07-15 15:10:35

3

如果你想要一個行:

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