似乎无法将表中的值正确复制到数据框中。如果运行 raw_data,它会输出所有值的列表。知道如何使其结构化吗?
pop_source = requests.get("http://zipatlas.com/us/tx/austin/zip-code-comparison/population-density.htm").text
soup = BeautifulSoup(pop_source, 'html5lib')
source = soup.find_all('td',class_ = 'report_data')
pop = pd.DataFrame(columns=['Zip Code','Population'])
row_data = [data.text for data in source]
temp_df = pd.DataFrame([row_data], columns=['#','Zip Code','Location','City', 'Population','People/Sq.Mile','National Rank'])
temp_df = temp_df[['Zip Code','Population']]
pop = pop.append(temp_df).reset_index(drop=True)
pop
最佳答案
代码中的一些内容:
上面的代码实际上不会循环任何内容。事实上,如果您尝试运行它,您应该会遇到大量错误。无法看到仅使用您提供的值循环相同值的输出。
缩进已关闭,
您引用了一个变量
source
尚未定义。您引用了一个变量cols
这也没有定义。您初始化一个数据框
pop
有 2 列,并尝试附加一个有 7 列的数据框。
这里发生了各种各样的问题。
您是否考虑过直接使用 Pandas 来形成数据框?您仍然可以使用 BeautifulSoup,但 pandas 可以为您完成这项工作,而且您似乎需要更多地练习使用 BeautifulSoup 迭代元素(实际上您甚至从未使用过 .find
或 .find_all
来定位标签与您想要的表关联。)
如果您需要 BeautifulSoup 的方式来做到这一点,请告诉我,我也可以提供这种方式,但说实话,这比仅仅使用 .read_html()
需要做更多的工作。这里有 Pandas 。
import pandas as pd
url = 'http://zipatlas.com/us/tx/austin/zip-code-comparison/population-density.htm'
tables = pd.read_html(url)
df = tables[11][1:]
df.columns = tables[11].iloc[0]
输出:
print (df)
0 # Zip Code ... People / Sq. Mile National Rank
1 1. 78705 ... 11008.66 #519
2 2. 78751 ... 5822.28 #1,374
3 3. 78752 ... 5435.92 #1,528
4 4. 78741 ... 5346.47 #1,562
5 5. 78723 ... 5175.95 #1,640
6 6. 78704 ... 5001.96 #1,713
7 7. 78758 ... 4954.80 #1,730
8 8. 78702 ... 4501.98 #2,015
9 9. 78757 ... 4380.92 #2,087
10 10. 78756 ... 4298.80 #2,139
11 11. 78745 ... 4063.22 #2,295
12 12. 78753 ... 3973.96 #2,350
13 13. 78703 ... 3491.54 #2,753
14 14. 78731 ... 3031.63 #3,167
15 15. 78759 ... 2998.68 #3,199
16 16. 78727 ... 2856.67 #3,371
17 17. 78749 ... 2795.02 #3,438
18 18. 78728 ... 2640.31 #3,614
19 19. 78721 ... 2568.43 #3,690
20 20. 78722 ... 2567.53 #3,692
21 21. 78729 ... 2366.94 #3,944
22 22. 78701 ... 2326.65 #3,995
23 23. 78748 ... 1961.73 #4,504
24 24. 78750 ... 1731.01 #4,870
25 25. 78744 ... 1464.78 #5,311
26 26. 78746 ... 1152.39 #5,971
27 27. 78717 ... 1081.05 #6,119
28 28. 78739 ... 768.80 #7,006
29 29. 78734 ... 698.96 #7,267
30 30. 78724 ... 555.85 #7,870
31 31. 78726 ... 543.24 #7,940
32 32. 78733 ... 510.92 #8,116
33 33. 78754 ... 484.73 #8,255
34 34. 78735 ... 474.14 #8,318
35 35. 78732 ... 416.13 #8,702
36 36. 78742 ... 321.40 #9,467
37 37. 78730 ... 257.86 #10,189
38 38. 78738 ... 213.29 #10,829
39 39. 78747 ... 194.02 #11,173
40 40. 78736 ... 187.88 #11,301
41 41. 78737 ... 143.90 #12,372
42 42. 78725 ... 116.87 #13,282
43 43. 78719 ... 93.88 #14,377
[43 rows x 7 columns]
使用 BeautifulSoup
这不是执行此操作的理想方法。虽然这个网站非常简单,带有 table
, tr
, td
标签。您可能想要的是首先获取所有行,然后迭代每一行以获取 <td>
标签。但你捕获了所有<td>
一口气标记。这仍然可以,但我们需要将其分成每一行。
然后我所做的就是将其分成 7 组,因为这就是有多少列。请注意,我做了一个巨大的假设,所有数据都在那里。如果不是,则表格将关闭或行、列将移动。
import requests
import pandas as pd
import bs4
# Create a function called "chunks" with two arguments, l and n:
def chunks(l, n):
# For item i in a range that is a length of l,
for i in range(0, len(l), n):
# Create an index range for l of n items:
yield l[i:i+n]
pop_source = requests.get("http://zipatlas.com/us/tx/austin/zip-code-comparison/population-density.htm").text
soup = bs4.BeautifulSoup(pop_source, 'html5lib')
source = soup.find_all('td',class_ = 'report_data')
pop = pd.DataFrame(columns=['#','Zip Code','Location','City', 'Population','People/Sq.Mile','National Rank'])
row_data = [data.text for data in source]
rows_data = list(chunks(row_data, 7))
for ele in rows_data:
temp_df = pd.DataFrame([ele], columns=['#','Zip Code','Location','City', 'Population','People/Sq.Mile','National Rank'])
pop = pop.append(temp_df).reset_index(drop=True)
关于pandas - BeautifulSoup 表到数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54335078/