42

ウェブページからすべてを取得したいiframe

コード:

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)

の結果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'}

の結果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'}]

コンテンツの価値が正しくないのはなぜですか?Iのときの値と同じだと思いprint(info)ます。

4

4 に答える 4

66

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)

これを達成する方法は他にもあります。たとえば、属性のリストを反復処理したり、リストまたは辞書内包表記を使用したりしますが、上記のコードの明瞭さを改善するのは困難です。

于 2012-07-15T14:25:04.783 に答える
42

Pythonlistオブジェクトを誤解しています。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
于 2012-07-15T14:37:49.123 に答える
5

If you want one line:

list_of_dict = [{} for i in range(list_len)]
于 2015-06-22T14:54:20.827 に答える
4

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')
...
于 2012-07-15T14:23:59.197 に答える