从Webscrape将一维数组文本转换为二维熊猫DF

时间:2020-05-13 11:27:22

标签: python pandas beautifulsoup

嗨,我已经使用以下代码对数据表进行了网络抓取:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np

df = pd.DataFrame()


for row in links2get:
    url = row
    response = requests.get(url)
    html_page = response.content
    soup = BeautifulSoup(html_page, 'html.parser')
    text = soup.find_all(text=True)
    for a in soup.select('.trackM'):
        b = a.get_text()
        array = np.array(b)
        print(array)
        #reshape = ????
        #df = df.append(reshape)

我对数组的输出是:

print(array):

Table Title


Heading 1
Heading 2
Heading 3
Heading 4
Heading 5


1084
316
No
72
Yes

编辑有时表中缺少值,因此元素的数量可能是奇数(例如5个标题列,但只有4个值)。

我希望将其重塑为一个DataFrame,使其看起来像:

print(df):

Heading 1   Heading 2   Heading 3   Heading 4   Heading 5
1084           316         No          72           Yes   

即时通讯在重塑时遇到问题,因此,如果有人提出任何建议,那将是很棒的!谢谢!

2 个答案:

答案 0 :(得分:2)

如果您知道表的网址和标题,则只需执行此操作。

import pandas as pd
df = pd.read_html(url, match='Table Title')[0]

如果将表格作为文本,请从美丽的汤中提取。您可以简单地做到这一点。

import pandas as pd
table_string = '''<table>
  <tr>
    <th>heading 1</th>
    <th>heading 2</th>
    <th>heading 3</th>
    <th>heading 4</th>
  </tr>
  <tr>
    <td>1084</td>
    <td>316</td>
    <td>No</td>
    <td>72</td>
    <td>Yes</td>
  </tr>
</table>'''

df = pd.read_html(table_string)[0]

输出:

   heading 1  heading 2 heading 3  heading 4 Unnamed: 4
0       1084        316        No         72        Yes

答案 1 :(得分:1)

您在正确的轨道上。但是从一系列干净的令牌开始。这将使下游更加简单。

[e for e in b.splitlines()[1:] if len(e)]

# b.splitlines()     -> Split the text output into a list at the linebreaks.
# b.splitlines()[1:] -> Drop the first element of the list ("Table Title")
# ... if len(e)      -> Only keep the token if it has length greater than zero (i.e. not the empty string.) 

至关重要的是,在这一部分中,您始终要创建一个具有偶数个元素的系列:

...
b = a.get_text()
s = pd.Series([e for e in b.splitlines()[1:] if len(e)])

Out[54]: 
0    Heading 1
1    Heading 2
2    Heading 3
3    Heading 4
4    Heading 5
5         1084
6          316
7           No
8           72
9          Yes

现在直接重塑为DataFrame。因为我们知道该系列中的元素数是偶数,所以我们可以将其整形为长度为int(len(s) / 2)的两行:

df = pd.DataFrame(s.values.reshape((2, int(len(s) / 2))))

           0          1          2          3          4
0  Heading 1  Heading 2  Heading 3  Heading 4  Heading 5
1       1084        316         No         72        Yes

现在,我们分配第一行中的列:

df.columns = df.iloc[0]

0  Heading 1  Heading 2  Heading 3  Heading 4  Heading 5
0  Heading 1  Heading 2  Heading 3  Heading 4  Heading 5
1       1084        316         No         72        Yes

最后,删除我们用于各列的行:

df.drop(df.index[0])

0 Heading 1 Heading 2 Heading 3 Heading 4 Heading 5
1      1084       316        No        72       Yes