【问题标题】:Scrape tables into dataframe with BeautifulSoup使用 BeautifulSoup 将表刮到数据框中
【发布时间】:2018-05-31 21:29:10
【问题描述】:

我正在尝试从硬币目录中抓取数据。

one of the pages。我需要将this data 刮入数据框

到目前为止,我有这个代码:

import bs4 as bs
import urllib.request
import pandas as pd

source = urllib.request.urlopen('http://www.gcoins.net/en/catalog/view/45518').read()
soup = bs.BeautifulSoup(source,'lxml')

table = soup.find('table', attrs={'class':'subs noBorders evenRows'})
table_rows = table.find_all('tr')

for tr in table_rows:
    td = tr.find_all('td')
    row = [tr.text for tr in td]
    print(row)                    # I need to save this data instead of printing it 

它产生以下输出:

[]
['', '', '1882', '', '108,000', 'UNC', '—']
[' ', '', '1883', '', '786,000', 'UNC', '~ $3.99']
[' ', " \n\n\n\n\t\t\t\t\t\t\t$('subGraph55337').on('click', function(event) {\n\t\t\t\t\t\t\t\tLightview.show({\n\t\t\t\t\t\t\t\t\thref : '/en/catalog/ajax/subgraph?id=55337',\n\t\t\t\t\t\t\t\t\trel : 'ajax',\n\t\t\t\t\t\t\t\t\toptions : {\n\t\t\t\t\t\t\t\t\t\tautosize : true,\n\t\t\t\t\t\t\t\t\t\ttopclose : true,\n\t\t\t\t\t\t\t\t\t\tajax : {\n\t\t\t\t\t\t\t\t\t\t\tevalScripts : true\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tevent.stop();\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t", '1884', '', '4,604,000', 'UNC', '~ $2.08–$4.47']
[' ', '', '1885', '', '1,314,000', 'UNC', '~ $3.20']
['', '', '1886', '', '444,000', 'UNC', '—']
[' ', '', '1888', '', '413,000', 'UNC', '~ $2.88']
[' ', '', '1889', '', '568,000', 'UNC', '~ $2.56']
[' ', " \n\n\n\n\t\t\t\t\t\t\t$('subGraph55342').on('click', function(event) {\n\t\t\t\t\t\t\t\tLightview.show({\n\t\t\t\t\t\t\t\t\thref : '/en/catalog/ajax/subgraph?id=55342',\n\t\t\t\t\t\t\t\t\trel : 'ajax',\n\t\t\t\t\t\t\t\t\toptions : {\n\t\t\t\t\t\t\t\t\t\tautosize : true,\n\t\t\t\t\t\t\t\t\t\ttopclose : true,\n\t\t\t\t\t\t\t\t\t\tajax : {\n\t\t\t\t\t\t\t\t\t\t\tevalScripts : true\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} \n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tevent.stop();\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t", '1890', '', '2,137,000', 'UNC', '~ $1.28–$4.79']
['', '', '1891', '', '605,000', 'UNC', '—']
[' ', '', '1892', '', '205,000', 'UNC', '~ $4.47']
[' ', '', '1893', '', '754,000', 'UNC', '~ $4.79']
[' ', '', '1894', '', '532,000', 'UNC', '~ $3.20']
[' ', '', '1895', '', '423,000', 'UNC', '~ $2.40']
['', '', '1896', '', '174,000', 'UNC', '—']

但是当我尝试将它保存到 Dataframe 并导出到 excel 时,它只包含最后一个值:

         0
0         
1         
2     1896
3         
4  174,000
5      UNC
6        —

【问题讨论】:

  • 你对save it to Dataframe做得怎么样?
  • 嗨,菲。接得好。我没有提到它。我刚刚又添加了 2 行:df = pd.DataFrame(row) 和 df.to_excel('coins.xlsx')。 for 循环中的数据被覆盖了。
  • 也可以使用df['col'].str.strip('\n')删除\n

标签: pandas dataframe web-scraping beautifulsoup


【解决方案1】:

Pandas 已经内置了将网络上的表格转换为数据框的方法:

table = soup.find_all('table')
df = pd.read_html(str(table))[0]

【讨论】:

  • 这应该是公认的答案。在此用例中使用 BeautifulSoup 毫无意义。
  • 这似乎是正确的,但行为不一致会丢失大量表行。
【解决方案2】:

试试这个

l = []
for tr in table_rows:
    td = tr.find_all('td')
    row = [tr.text for tr in td]
    l.append(row)
pd.DataFrame(l, columns=["A", "B", ...])

【讨论】:

  • 这太棒了!谢谢
【解决方案3】:

试试:

import pandas as pd
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
table = soup.find('table', attrs={'class':'subs noBorders evenRows'})
table_rows = table.find_all('tr')

res = []
for tr in table_rows:
    td = tr.find_all('td')
    row = [tr.text.strip() for tr in td if tr.text.strip()]
    if row:
        res.append(row)


df = pd.DataFrame(res, columns=["Year", "Mintage", "Quality", "Price"])
print(df)

输出:

   Year  Mintage Quality    Price
0  1882  108,000     UNC        —
1  1883  786,000     UNC  ~ $4.03

【讨论】:

  • 嗨,拉克什。感谢您的回答。它也适用于我。我只是选择了 phi 的答案,因为它促进了我昨天的工作 :) 干杯!
【解决方案4】:

请注意...这部分 Rakesh 代码意味着只有包含文本的 HTML 行才会包含在数据框中,因为如果 row 是空列表,则不会附加行:

if row:
    res.append(row)

在我的用例中存在问题,我想稍后比较 HTML 和数据框表的行索引。我只需要将其更改为:

res.append(row)

此外,如果行中的单元格为空,则不会包含在内。这会弄乱列。所以我改变了

row = [tr.text.strip() for tr in td if tr.text.strip()]

row = [d.text.strip() for d in td]

但是,否则,它对我有用。谢谢:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2018-04-17
    • 2022-08-15
    相关资源
    最近更新 更多