pandas - BeautifulSoup 表到数据框
问题描述
似乎无法将表中的值正确复制到数据框中。如果您运行 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]
用美丽的汤
这不是执行此操作的理想方法。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)
推荐阅读
- visual-studio-code - 如何将输出或终端移回窗口布局中的面板?
- mysql - 在mysql中进行查询以计算成员
- c# - 如何防止在asp.net LinkButton OnClick函数上重新加载页面
- ansible - 基于过滤器获取 ansible 库存
- c# - SkipWhile TakeWhile,然后也取上面的行直到匹配
- javascript - 无论如何要删除 JSON 对象数组 JavaScript 中特定键/值的引号
- java - 如何有效地选择通过某些点的网格上的线
- c# - MongoDB 在序列化时忽略属性,但在反序列化时不忽略
- python - 我正在实现机器学习线性回归算法我得到名称错误(NameError:名称'names'未定义)
- angular - Angular 9:调用 API 时的浏览器启动器