【问题标题】:how can you split cell data into different cells in python?如何在 python 中将单元格数据拆分为不同的单元格?
【发布时间】:2021-11-08 10:27:50
【问题描述】:

我正在尝试将此网页解析为 pandas 数据框以进行分析,但该页面的设置使得该表只有两列使用,一列包含名称,另一列包含所有其他信息细胞。

例如,下面是我的代码:

import bs4
from bs4 import BeautifulSoup
from urllib.request import urlopen
import pandas as pd

url = "https://education.scripps.edu/alumni/graduate-alumni-list/index.html"
page = urlopen(url)
html = page.read().decode("utf-8")
soup = BeautifulSoup(html, "html.parser")

table = soup.find('tbody')
td = table.find_all('td')
data = []
for element in td:
    sub_data = []
    for sub_element in element:
        try:
            sub_data.append(sub_element.get_text())
        except:
            continue
    data.append(sub_data)

dataFrame = pd.DataFrame(data = data)
df = dataFrame[[1,3]]
df = df.dropna()

所以 df.iat[0,1] 将包含课程、防御年份、顾问、论文题目和本科院校。 HTML 仅使用“br”和“strong”来分隔这些值,我想知道是否有任何方法可以将此文本分成不同的列,以便列是“名称”、“程序”、“国防年”和这样,而不是一个包含所有信息的单元格。

非常感谢!

【问题讨论】:

    标签: python pandas dataframe web-scraping beautifulsoup


    【解决方案1】:

    在 try: 之后和代码中的 sub_data.append 行之前,你应该用“
    ”分割你的 sub_element 文本。您可以尝试以下方法:

    sub_data_splitted = sub_element.get_text().split("<br>").
    # After that you are able to use each field of the data i.e. 
    program = sub_data_splitted[0].split(":")[1]
    defense_year = sub_data_splitted[1].split(":")[1]
    advisor = sub_data_splitted[2].split(":")[1]
    dissertation_title = sub_data_splitted[3].split(":")[1]
    ug_institution = sub_data_splitted[4].split(":")[1]
    

    【讨论】:

      【解决方案2】:

      你可以这样做。

      • 您可以使用.stripped_strings() 从表的每个&lt;tr&gt; 中获取数据列表。
      • 由于您只需要值而不需要标题(如姓名、国防年等)。使用列表推导仅选择所需的值。
      • 将列表附加到数据框。

      这是如何完成的。

      import requests
      from bs4 import BeautifulSoup
      import pandas as pd
      
      URL = "https://education.scripps.edu/alumni/graduate-alumni-list/index.html"
      page = requests.get(URL)
      
      soup = BeautifulSoup(page.text, "lxml")
      t = soup.find('table').find('tbody')
      trs = t.find_all('tr')
      data = []
      for i in trs:
          l = [x for i,x in enumerate(list(i.stripped_strings)) if i%2 == 0]
          data.append(l)
      
      df = pd.DataFrame(data=data)
      
                                      0  ...     6
      0              Abbott, PhD, Jason  ...  None
      1      Adam, PhD, Gregory Charles  ...  None
      2         Adhikari, PhD, Pramisha  ...  None
      3    Al-Bassam, PhD, Jawdat M. H.  ...  None
      4        Albertshofer, PhD, Klaus  ...  None
      ..                            ...  ...   ...
      682           Zhou, PhD, Jiacheng  ...  None
      683    Zhou, PhD, Zhaohui (Sunny)  ...  None
      684                Zhu, PhD, Ruyi  ...  None
      685                 Zhu, PhD, Yan  ...  None
      686          Zuhl, PhD, Andrea M.  ...  None
      
      [687 rows x 7 columns]
      

      【讨论】:

        【解决方案3】:

        这是你想要做的吗?

        import bs4
        from bs4 import BeautifulSoup
        from urllib.request import urlopen
        import pandas as pd
        
        url = "https://education.scripps.edu/alumni/graduate-alumni-list/index.html"
        page = urlopen(url)
        html = page.read().decode("utf-8")
        soup = BeautifulSoup(html, "html.parser")
        
        table = soup.find('tbody')
        td = table.find_all('td')
        data = {}
        names = []
        prev_name = None
        for element in td:
            sub_data = {}
            for sub_element in element:
                try:
                    data[sub_element['alt']] = {}
                    prev_name = sub_element['alt']
                except:
                    sub_element = str(sub_element).replace('</strong>', '').replace('<br/>', '</strong>')
                    temp = BeautifulSoup(sub_element)
                    if len(temp.find_all('strong')) > 0:
                        temp = [str(i.string) for i in temp.find_all('strong') if i.string is not None]
                        temp = {i.split(':', 1)[0] : i.split(':', 1)[1] for i in temp if ':' in i}
                        data[prev_name] = temp
        
        
        df = pd.DataFrame(data = data)
        df = df.T.reset_index()
        df.rename(columns={'index' : 'Name'}, inplace=True)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多