【问题标题】:How to convert multiple html tables into a pandas dataframe by using a customized function?如何使用自定义函数将多个 html 表转换为 pandas 数据框?
【发布时间】:2021-05-13 10:38:05
【问题描述】:

我正在尝试将多个 html 表转换为 pandas 数据框, 对于这个任务,我定义了一个函数来将所有这些 html 表作为 pandas 数据框返回,

然而,当函数返回一个空列表 [] 时,它的想法是它返回一个 pandas 数据帧。

这是我迄今为止尝试过的:

以列表的形式获取所有需要的链接

import requests
from bs4 import BeautifulSoup
import lxml
import html5lib
import pandas as pd
import string

###  defining a list for all the needed links ###

first_url='https://www.salario.com.br/tabela-salarial/?cargos='
second_url='#listaSalarial'
allTheLetters = string.ascii_uppercase

links = []

for letter in allTheLetters:
   links.append(first_url+letter+second_url)

定义一个函数


### defining function to parse html objects ###

def getUrlTables(links):
  for link in links:

      # requesting link, parsing and finding tag:table #
      page = requests.get(link)
      soup = BeautifulSoup(page.content, 'html.parser')
      tab_div = soup.find_all('table', {'class':'listas'})

  # writing html files into directory #
  with open('listas_salariales.html', "w") as file:
    file.write(str(tab_div))
    file.close
  
  # reading html file as a pandas dataframe #
  tables=pd.read_html('listas_salariales.html')
  return tables 

测试输出

getUrlTables(links)

[]

我在getUrlTables() 中遗漏了什么吗?

有没有更简单的方法来完成这项任务?

【问题讨论】:

  • 1.您正在循环浏览链接并在最后一个链接中保存表到文件(所有其他文件都被丢弃)。 2. 这将不是一个格式良好的 HTML 文档(没有 html 或 body 元素) - 您的 html 文件看起来如何作为文本以及当您在浏览器中打开它时它看起来如何?
  • @Rob Raymond,确实,可能是可以迭代这些 html 的额外行;它看起来一样,但不像我想要的桌子,在任何一个......

标签: python html pandas web-scraping


【解决方案1】:

以下代码将从所有链接中获取 HTML,解析它们以提取表数据并构造一个大型组合数据帧(我没有将中间数据帧存储到磁盘,如果大小可能需要的表变得太大):

import requests
from bs4 import BeautifulSoup
import lxml
import html5lib
import pandas as pd
import string

###  defining a list for all the needed links ###

first_url='https://www.salario.com.br/tabela-salarial/?cargos='
second_url='#listaSalarial'
allTheLetters = string.ascii_uppercase

links = []

for letter in allTheLetters:
    links.append(first_url+letter+second_url)

### defining function to parse html objects ###

def getUrlTables(links, master_df):
    for link in links:
        page = requests.get(link)
        soup = BeautifulSoup(page.content, 'lxml')   # using the lxml parser
        try:
            table = soup.find('table', attrs={'class':'listas'})

            # finding table headers
            heads = table.find('thead').find('tr').find_all('th')
            colnames = [hdr.text for hdr in heads]
            #print(colnames)
            
            # Now extracting the values
            data = {k:[] for k in colnames}
            rows = table.find('tbody').find_all('tr')
            for rw in rows:
                for col in colnames:
                    cell = rw.find('td', attrs={'data-label':'{}'.format(col)})
                    data[col].append(cell.text)

            # Constructing a pandas dataframe using the data just parsed
            df = pd.DataFrame.from_dict(data)
            master_df = pd.concat([master_df, df], ignore_index=True)
        except AttributeError as e:
            print('No data from the link: {}'.format(link))
    return master_df


master_df = pd.DataFrame()
master_df = getUrlTables(links, master_df)
print(master_df)

上述代码的输出如下:

         CBO                    Cargo  ... Teto Salarial Salário Hora
0     612510            Abacaxicultor  ...      2.116,16         6,86
1     263105                    Abade  ...      5.031,47        17,25
2     263105                 Abadessa  ...      5.031,47        17,25
3     622020  Abanador na Agricultura  ...      2.075,81         6,27
4     862120  Abastecedor de Caldeira  ...      3.793,98        11,65
...      ...                      ...  ...           ...          ...
9345  263110      Zenji (missionário)  ...      3.888,52        12,65
9346  723235                 Zincador  ...      2.583,20         7,78
9347  203010               Zoologista  ...      4.615,45        14,21
9348  203010                  Zoólogo  ...      4.615,45        14,21
9349  223310              Zootecnista  ...      5.369,59        16,50

[9350 rows x 8 columns]

【讨论】:

  • 请验证是否从网站上正确捕获了所有数据!
  • import pandas as pd 之后使用pd.set_option('display.max_columns', None) 来显示所有列。要重置此行为,请使用pd.reset_option('display.max_columns')
猜你喜欢
  • 2013-04-07
  • 2019-07-11
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多