You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

网页爬取时如何动态合并不同列的DataFrame?

问题描述

我正在开发一款网页爬取工具,需要从主表每行对应的链接进入子页面,提取子页面表格数据并合并为完整的DataFrame。问题在于每个子表格的列集合可能不同,且无法预知所有列类型。

我刚学Python一周,尝试多种方案后,目前通过循环生成临时DataFrame并与主DataFrame合并,但卡在合并步骤。以下是我的代码:

# 创建主DataFrame
link1 = links[0]
url_linked = url_l + link1
page_linked = requests.get(url_linked)
soup_linked = BeautifulSoup(page_linked.text, 'lxml')
table_linked = soup_linked.find('table', class_="XXXXX")

headers_link = []
headers_unique = []
for i in table_linked.find_all('th'):
    title_link = i.text
    title_link = map(str, title_link)  # 此处存在问题:单个字符串被转成迭代器
    headers_link.append(title_link)

headers_unique = headers_link
mydata_link = pd.DataFrame(columns=headers_link)

count = 1

for link in links:
    url_linked = url_l + link
    page_linked = requests.get(url_linked)
    soup_linked = BeautifulSoup(page_linked.text, 'lxml')
    table_linked = soup_linked.find('table', class_="table table-directory-responsive")

    row2 = []
    n_columns = len(table_linked.find_all('th'))

    # 填充主DataFrame
    if count == 1:
        for j in table_linked.find_all('tr'):
            row_data = j.find_all('td')
            row = [i.text for i in row_data]
            row2.append(row)
        
        lenght_link = len(mydata_link)
        row2.remove([''])  # 移除空行
        mydata_link.loc[lenght_link] = row2  # 此处错误:row2是列表的列表,不能直接赋值给一行
        print(mydata_link)

        print('Completato link ' + str(count))
        count = count + 1

    # 创建临时DataFrame
    else:      
        headers_test = []
        for i in table_linked.find_all('th'):
            title_test = i.text
            title_test = map(str, title_test)
            headers_test.append(title_test)

        mydata_temp = pd.DataFrame(columns=headers_test)

        for j in table_linked.find_all('tr'):
            row_data = j.find_all('td')
            row = [i.text for i in row_data]
            row2.append(row)
        
        lenght_link = len(mydata_link)
        row2.remove([''])
        mydata_temp.loc[lenght_link] = row2  # 同样的赋值错误
        print(mydata_temp)
        
        # 尝试合并两个DataFrame
        headers_unique = set(headers_unique).intersection(headers_test)
        mydata_link = mydata_link.merge(mydata_temp, on=[headers_unique], how='outer')  # merge用法错误,此处不需要关联合并
        print(mydata_link)
        print('Completed link ' + str(count))
        count = count + 1

我需要实现的功能是将如下两个DataFrame:

输入DataFrame 1

ABC
123

输入DataFrame 2

CADE
4567

合并为如下结果:

期望输出DataFrame

ABCDE
123NaNNaN
5NaN467

解决方案

你的核心问题是误用了merge方法——merge用于按关联键合并表(类似SQL JOIN),而你需要的是把不同子页的行纵向拼接,自动补全缺失列的NaN。另外代码里还有表头处理、行数据赋值的细节错误,下面是修正后的方案:

步骤1:封装子页表格提取函数

先写一个通用函数,负责从单个链接提取表格并返回DataFrame,避免重复代码:

import requests
from bs4 import BeautifulSoup
import pandas as pd

def extract_subpage_table(url):
    page = requests.get(url)
    soup = BeautifulSoup(page.text, 'lxml')
    table = soup.find('table', class_="table table-directory-responsive")
    
    # 提取干净的表头文本
    headers = [th.text.strip() for th in table.find_all('th')]
    
    # 提取有效行数据
    rows = []
    for tr in table.find_all('tr'):
        tds = tr.find_all('td')
        # 只保留列数和表头一致的有效行
        if len(tds) == len(headers):
            row = [td.text.strip() for td in tds]
            rows.append(row)
    
    return pd.DataFrame(rows, columns=headers)

步骤2:遍历链接收集并拼接DataFrame

把每个子页的DataFrame收集到列表,最后一次性纵向拼接:

# 假设url_l(主链接前缀)和links(子页链接列表)已定义
all_dfs = []
for idx, link in enumerate(links, 1):
    full_url = url_l + link
    df = extract_subpage_table(full_url)
    all_dfs.append(df)
    print(f'完成链接 {idx}')

# 拼接所有DataFrame,自动合并所有列,缺失值填充NaN
final_df = pd.concat(all_dfs, ignore_index=True)
print(final_df)

关键说明

  1. 为什么用concat而非merge:pd.concat([df1, df2], ignore_index=True)会按顺序拼接所有行,自动识别所有出现过的列,无数据的列自动填充NaN,完全匹配你的需求。
  2. 表头修正:之前用map(str, title_link)会把单个字符串转成字符迭代器,导致表头失效,直接用th.text.strip()就能得到干净的表头文本。
  3. 行数据过滤:通过len(tds) == len(headers)过滤空行或无效行,比手动删除特定空列表更可靠。
  4. 代码简化:封装函数后循环逻辑更清晰,新手更容易理解和维护。

内容的提问来源于stack exchange,提问作者Shattered

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:05:19