Je veux obtenir tous les iframe
d'une page Web.
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)
résultat de 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'}
résultat de 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'}]
Pourquoi la valeur du contenu n'est-elle pas correcte? C'est supposé être identique à la valeur quand I print(info)
.
Vous ne créez pas de dictionnaire distinct pour chaque iframe, vous ne faites que modifier le même dictionnaire, et vous continuez à ajouter des références supplémentaires à ce dictionnaire dans votre liste.
Rappelez-vous que lorsque vous faites quelque chose comme content.append(info)
, vous ne faites pas de copie des données, vous ajoutez simplement une référence aux données.
Vous devez créer un nouveau dictionnaire pour chaque iframe.
for iframe in soup.find_all('iframe'):
info = {}
...
Mieux encore, vous n'avez pas besoin de créer un dictionnaire vide au préalable. Il suffit de créer le tout à la fois:
for iframe in soup.find_all('iframe'):
info = {
"src": iframe.get('src'),
"height": iframe.get('height'),
"width": iframe.get('width'),
}
content.append(info)
Il existe d'autres moyens d'y parvenir, tels que parcourir une liste d'attributs ou d'utiliser des listes de compréhension ou des dictionnaires, mais il est difficile d'améliorer la clarté du code ci-dessus.
Vous avez mal compris l'objet Python list
. Il ressemble à un C pointer-array
. Il ne "copie" pas réellement l'objet que vous lui ajoutez. Au lieu de cela, il stocke simplement un "pointeur" sur cet objet.
Essayez le code suivant:
>>> 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}]
Alors, pourquoi print(dlist)
n'est-il pas identique à print(d)
?
Le code suivant vous montre la raison:
>>> 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
Ainsi, vous pouvez voir que tous les éléments du dlist
pointe en fait sur le même objet dict
.
La vraie réponse à cette question sera d’ajouter la "copie" de l’élément cible, en utilisant 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}]
Essayez l’astuce id()
, vous pouvez voir que les éléments de la liste indiquent des objets complètement différents.
>>> 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
info
est un pointeur sur un dictionnaire - vous continuez à ajouter le même pointeur à votre liste contact
.
Insérer info = {}
dans la boucle et cela devrait résoudre le problème:
...
content = []
for iframe in soup.find_all('iframe'):
info = {}
info['src'] = iframe.get('src')
info['height'] = iframe.get('height')
info['width'] = iframe.get('width')
...
Si vous voulez une ligne:
list_of_dict = [{} for i in range(list_len)]