为什么这个列表返回相同的值?

时间:2015-07-19 21:24:25

标签: python web-scraping beautifulsoup

我正在尝试为http://www.virginiaequestrian.com/main.cfm?action=greenpages&GPType=8抓取所有表值并将值放在列表列表中。出于某种原因,我似乎无法理解。将信息字典附加到数据列表只会将一个值放入364次(表的长度)。我在循环中单独打印每一行和值,我知道我正在抓取正确的元素/值,但是当我尝试将值放入数据列表时,一切似乎都会崩溃。

当我做错时,有人可以告诉我吗?

from bs4 import BeautifulSoup
import requests

r=requests.get('http://www.virginiaequestrian.com/main.cfm?action=greenpages&GPType=8')
soup=BeautifulSoup(r.content,'html5lib')

data = []
info = {}

tbl = soup.findAll('table')[2]
for tr in tbl.findAll('tr')[3:]:
    for td in tr.findAll('td')[0]:
        value= td.string
        info['Name']=value
    for td in tr.findAll('td')[1]:
        value= td.string
        info['City']=value
    for td in tr.findAll('td')[2]:
        value= td.string
        info['Phone']=value
    for td in tr.findAll('td')[3]:
        value = "http://www.virginiaequestrian.com/{}".format(td.a['href'])
        info['ListURL']=value
        data.append(info)
print data

1 个答案:

答案 0 :(得分:2)

python中的对象(如您的info dict)使用对其基础数据结构的引用。在调用data.append(info)时你基本上做的是一遍又一遍地对同一个词典添加相同的引用。

你可以做的是(重新)在最外面的for循环的每次迭代中创建你的info dict:

for tr in tbl.findAll('tr')[3:]:
    info = {}
    ...

或将您的词典副本附加到您的列表中:

data.append(info.copy())

每次都创建一个新对象。

您还可以简化内部for循环,因为不一定需要迭代一个值:

for td in tr.findAll('td')[0]:
    value= td.string
    info['Name']=value
for td in tr.findAll('td')[1]:
    value= td.string
    info['City']=value
for td in tr.findAll('td')[2]:
    value= td.string
    info['Phone']=value
for td in tr.findAll('td')[3]:
    value = "http://www.virginiaequestrian.com/{}".format(td.a['href'])
    info['ListURL']=value

可以成为

name, city, phone, url = tr.findAll('td')[:4]
info['Name'] = name.string
info['City'] = city.string
info['Phone'] = phone.string
info['ListURL'] = "http://www.virginiaequestrian.com/{}".format(url.a['href'])