首页 > 解决方案 > 从网页中抓取带有隐藏行的表格

问题描述

我试图刮掉这张桌子(https://rk.americaeconomia.com/display/embed/multilatinas/2019)。如您所见,该表有两种类型的行:“dataRow”和“extraDataRow”,并且这两种类型的行都指向同一个公司/公司。

我正在尝试下面的代码,但无法使用所需信息创建字典。感谢您做两件事的任何帮助:(1)使用两种类型的行刮取完整的表,以及(2)创建一个数据框来存储与每个公司相关的“所有”数据。

提前致谢。

def getHTMLContent(link):
html = urlopen(link)
soup = BeautifulSoup(html, 'html.parser')
return soup

content = getHTMLContent('https://rk.americaeconomia.com/display/embed/multilatinas/2019')
tables = content.find_all('table')
table = content.find('table', {'class': 'table'})
for tr in table.find_all('tr'):
if(tr.get('class')==['dataRow']):
    print(cell.text)
elif ((tr.get('class') == ['extraDataRow'])):
    print(cell.text)

我的输出应该是这样的

Firm   Country    Sector   %Multi  Ranking18   Total sales 2018  ...



Cols 1-4 are in "dataRow". Cols 5, 6 .......  are in "extraDataRow". 

在“extraDataRow”中,我有 32 列,其中包含每个公司的额外信息,我希望将所有这 32 列的信息与前四列(“dataRow”)的信息相结合。我想要表格格式的所有信息。

标签: python-3.xbeautifulsoup

解决方案


这是我想出的一个快速解决方案。

我创建了一个函数来从找到的第一个 extraDetails 行和找到的第一个正常行中获取所有标题。然后我得到所有正常的行。我遍历所有行并使用 data-target 属性来获取额外的详细信息行。使用这些数据,我创建了一个对象,使用标题作为参考,以请求的方式格式化数据。

from urllib.request import urlopen

from bs4 import BeautifulSoup

def get_headers(soup):
    header_names = []
    headers = soup.find('thead').find_all('th')

    for h in headers:
        header_names.append(h.text)

    extra_headers = soup.find(attrs={
            'class': 'extraDataRow'
        }).find_all(attrs={
            'class': 'extraMiniHeader'
        })

    for h in extra_headers:
        header_names.append(h.text)

    return header_names

html = urlopen('https://rk.americaeconomia.com/display/embed/multilatinas/2019')
soup = BeautifulSoup(html, 'html.parser')

headers = get_headers(soup)
rows = soup.find_all(attrs={'class': 'dataRow'})
results = []
for r in rows:
    result = {}
    data = r.find_all('td')
    data_count = len(data)
    for i in range(0, data_count):
        result[headers[i]] = data[i].text
    extra = soup.find(attrs={
        'data-link': r.attrs.get('data-target'), 
        'class': 'extraDataRow'
    })
    extra_data = extra.find_all(attrs={
            'class': 'extraMiniValue'
        })

    extra_count = len(extra_data)

    for i in range(data_count, data_count + extra_count):
        result[headers[i]] = extra_data[i - data_count].text

    results.append(result)

# Prints First Result
print(results[0])

推荐阅读