我正在从网站上搜集选举数据并尝试将其存储在数据框中
import pandas as pd
import bs4
import requests
columns = ['Candidate','Party','Criminal Cases','Education','Age','Total Assets','Liabilities']
df = pd.DataFrame(columns = columns)
ind=1
url = requests.get("http://myneta.info/up2007/index.php?action=show_candidates&constituency_id=341")
soup = bs4.BeautifulSoup(url.content)
for content in soup.findAll("td")[16:]:
df.iloc[ind//7,ind%7-1] = content.text
ind=ind+1
print(df)
基本上,content.text的每次迭代都会为我提供一个我将在表中填充的值。循环将按以下顺序将值填充到df -
df[0,0]
df[0,1]
df[0,2]
.
.
.
df[1,0]
df[1,1]
.
.
等等。不幸的是,iloc正在抛出一个错误 - “单个位置索引器超出范围”。有趣的是当我在for循环之外尝试df.iloc[0,0] = content.text
(在一个单独的单元格中用于测试目的)时,代码正常工作,但在for循环中它会产生错误。我相信这可能是微不足道的,但我无法理解。请帮助
答案 0 :(得分:13)
DataFrame.iloc
无法扩大其目标对象。这曾经是错误消息,但自版本0.15以来已更改。
通常,DataFrame
并不意味着一次构建一行。这是非常低效的。相反,您应该创建一个更传统的数据结构并从中填充DataFrame
:
table = soup.find(id='table1')
rows = table.find_all('tr')[1:]
data = [[cell.text for cell in row.find_all('td')] for row in rows]
df = pd.DataFrame(data=data, columns=columns)
从您的请求中检查页面看来,您在表格后面是id“table1”,其中第一行是标题(该页面的作者选择不当,应该在{{ 1}},而不是身体)。因此,跳过第一行(<thead>
),然后从行的单元格构建列表列表。
当然你也可以让pandas担心解析和所有:
[1:]
答案 1 :(得分:0)
这是一种解决方法。我和我的熊猫版本有同样的iloc错误。这个修改过的代码通过在为每个迭代分配值之前创建一个空白记录(通过创建一行数据帧并附加到现有数据帧)来克服它。
import pandas as pd
import bs4
import requests
columns = ['Candidate','Party','Criminal Cases','Education','Age','Total Assets','Liabilities']
df = pd.DataFrame(columns = columns)
ind=1
url = requests.get("http://myneta.info/up2007/index.php?action=show_candidates&constituency_id=341")
soup = bs4.BeautifulSoup(url.content)
for content in soup.findAll("td")[16:]:
data = pd.DataFrame({columns[0]:"",
columns[1]:"",
columns[2]:"",
columns[3]:"",
columns[4]:"",
columns[5]:"",
columns[6]:"",
},index=[0])
df=df.append(data,,ignore_index=True)
df.iloc[ind//7,ind%7-1] = content.text
ind=ind+1