0

0

利用BeautifulSoup和Pandas高效抓取并结构化网页表格数据

心靈之曲

心靈之曲

发布时间:2025-09-10 13:56:17

|

374人浏览过

|

来源于php中文网

原创

利用BeautifulSoup和Pandas高效抓取并结构化网页表格数据

本教程详细介绍了如何使用Python的requests、BeautifulSoup和Pandas库从复杂网页中精确提取结构化表格数据。我们将以抓取特定区域的积雪深度数据为例,演示从识别HTML元素、解析表格结构到最终构建Pandas DataFrame的完整过程,并提供实用的代码示例和注意事项。

1. 背景与目标

在数据分析和自动化任务中,我们经常需要从网页上获取特定信息。当目标数据以表格形式呈现时,直接通过简单的元素选择器可能无法有效获取其结构化内容。本教程的目标是演示如何从一个包含积雪深度信息的网页(例如:https://www.yr.no/nb/sn%c3%b8dybder/no-46/norge/vestland)中,准确提取特定区域的积雪深度数据,并将其整理成易于分析的pandas dataframe。

2. 初始尝试与挑战

许多初学者在尝试抓取网页数据时,可能会先尝试查找页面上所有包含特定值的通用标签,例如通过soup.find_all("span", {"class": "snow-depth__value"})来获取所有带有snow-depth__value类的span标签。这种方法虽然能获取到所有匹配的值,但存在以下问题:

  • 缺乏上下文: 仅仅获取值无法知道它属于哪个区域、哪个时间点,数据是零散的。
  • 结构化困难: 将这些零散的值与对应的标题或描述关联起来,并最终放入DataFrame中,需要额外的逻辑处理,效率低下且容易出错。

正确的思路是首先识别目标数据在网页上的整体结构,特别是当数据呈现为表格时。

3. 精确抓取表格数据:分步指南

我们将利用requests库获取网页内容,BeautifulSoup解析HTML,然后识别并提取表格的标题和每一行数据,最终使用Pandas构建DataFrame。

3.1 引入必要的库

首先,导入我们将用到的Python库:

import requests
from bs4 import BeautifulSoup
from bs4.element import ResultSet, Tag
from typing import Generator, List
from pandas import DataFrame

3.2 发送HTTP请求并解析HTML

使用requests.get()方法获取网页的HTML内容,然后使用BeautifulSoup对其进行解析。

# 目标网页URL
url = 'https://www.yr.no/nb/sn%C3%B8dybder/NO-46/Norge/Vestland'

# 发送GET请求获取网页内容
response: requests.Response = requests.get(url)
html: str = response.content

# 使用BeautifulSoup解析HTML
soup: BeautifulSoup = BeautifulSoup(html, 'html.parser')

3.3 识别并提取表格头部(列名)

表格的列名通常位于

LongShot
LongShot

LongShot 是一款 AI 写作助手,可帮助您生成针对搜索引擎优化的内容博客。

下载
标签中。通过检查网页的HTML结构,我们可以发现列名所在的 标签具有特定的类名,例如fluid-table__cell--heading。
# 查找所有表格头部单元格
table_headers: ResultSet = soup.find_all('th', class_='fluid-table__cell--heading')

# 提取列名文本
# 注意:在BeautifulSoup中,由于'class'是Python的保留关键字,
# 在find_all/find方法中作为参数传递时需要使用'class_'。
colnames: List[str] = [th.text for th in table_headers]
print("提取到的列名:", colnames)

3.4 识别并提取表格行数据

表格的每一行数据通常位于

标签中。同样,通过检查HTML结构,我们可以找到包含数据的 标签具有特定的类名,例如fluid-table__row fluid-table__row--link。

为了高效处理数据,我们可以使用生成器表达式(Generator comprehension)来延迟计算,避免一次性加载所有数据到内存,这对于大型表格尤其有用。

# 查找所有表格数据行
table_rows: ResultSet = soup.find_all('tr', class_='fluid-table__row fluid-table__row--link')

# 使用生成器表达式提取每行中的所有单元格文本
# 每个子生成器代表一行数据,包含该行所有子元素的文本内容
# 这里的child.text会提取标签下所有子标签(如)的文本
row_data: Generator[Generator[str, None, None], None, None] = (
    (child.text for child in row.children) for row in table_rows
)

# 打印前几行数据以供检查(可选)
print("\n提取到的部分行数据:")
for i, row in enumerate(row_data):
    if i >= 3: # 只打印前3行
        break
    print(list(row)) # 将生成器转换为列表以便打印

3.5 构建Pandas DataFrame

有了列名和行数据,我们就可以轻松地使用Pandas的DataFrame构造函数来创建结构化的数据表。

# 重新获取row_data,因为上一步的打印操作已经消耗了生成器
table_rows_for_df: ResultSet = soup.find_all('tr', class_='fluid-table__row fluid-table__row--link')
row_data_for_df: Generator[Generator[str, None, None], None, None] = (
    (child.text for child in row.children) for row in table_rows_for_df
)

# 创建Pandas DataFrame
df: DataFrame = DataFrame(row_data_for_df, columns=colnames)

# 尝试将所有列的数据类型转换为整数,如果遇到无法转换的值则忽略(保持原类型)
df = df.astype(int, errors='ignore')

print("\n最终生成的Pandas DataFrame:")
print(df.head())

4. 完整代码示例

将以上步骤整合,得到完整的代码如下:

import requests
from bs4 import BeautifulSoup
from bs4.element import ResultSet, Tag
from typing import Generator, List
from pandas import DataFrame

def scrape_snow_depth_data(url: str) -> DataFrame:
    """
    从指定的URL抓取积雪深度表格数据并返回Pandas DataFrame。

    Args:
        url (str): 目标网页的URL。

    Returns:
        DataFrame: 包含积雪深度数据的Pandas DataFrame。
    """
    try:
        response: requests.Response = requests.get(url)
        response.raise_for_status()  # 检查HTTP请求是否成功
    except requests.exceptions.RequestException as e:
        print(f"请求网页失败: {e}")
        return DataFrame()

    html: str = response.content
    soup: BeautifulSoup = BeautifulSoup(html, 'html.parser')

    # 提取表格头部(列名)
    table_headers: ResultSet = soup.find_all('th', class_='fluid-table__cell--heading')
    colnames: List[str] = [th.text.strip() for th in table_headers] # 使用.strip()清除空白符

    # 提取表格行数据
    table_rows: ResultSet = soup.find_all('tr', class_='fluid-table__row fluid-table__row--link')

    # 使用生成器表达式提取每行中的所有单元格文本
    # 注意:这里需要确保每个row.children都能正确解析出所需的数据,
    # 有时需要更精确的选择器如row.find_all('td')
    row_data: Generator[List[str], None, None] = (
        [child.text.strip() for child in row.children if isinstance(child, Tag)] 
        for row in table_rows
    )

    # 过滤掉空行或不完整的行,确保每行的数据量与列名数量一致
    filtered_row_data = [row for row in row_data if len(row) == len(colnames)]

    # 创建Pandas DataFrame
    df: DataFrame = DataFrame(filtered_row_data, columns=colnames)

    # 尝试将所有列的数据类型转换为整数,如果遇到无法转换的值则忽略
    # 可能会有非数字列,所以使用errors='ignore'
    for col in df.columns:
        try:
            df[col] = pd.to_numeric(df[col], errors='ignore')
        except:
            pass # 无法转换为数字的列保持原样

    return df

if __name__ == "__main__":
    import pandas as pd # 在主执行块中导入pd,避免全局污染

    target_url = 'https://www.yr.no/nb/sn%C3%B8dybder/NO-46/Norge/Vestland'
    snow_depth_df = scrape_snow_depth_data(target_url)

    if not snow_depth_df.empty:
        print("成功获取并处理积雪深度数据:")
        print(snow_depth_df.head())
        print("\nDataFrame信息:")
        snow_depth_df.info()
    else:
        print("未能获取到数据。")

5. 注意事项与最佳实践

  • 网站结构变化: 网页的HTML结构可能会随时改变。如果代码突然失效,很可能是因为网站更新了其HTML标签、类名或结构。这时需要重新检查目标网页的HTML,并调整选择器。
  • robots.txt: 在进行网页抓取前,务必检查网站的robots.txt文件(例如:https://www.yr.no/robots.txt),了解网站的抓取策略和允许抓取的范围。遵守这些规则是道德和法律要求。
  • 请求频率: 避免在短时间内发送大量请求,这可能导致IP被封禁或对网站服务器造成不必要的负担。可以使用time.sleep()在请求之间添加延迟。
  • 错误处理: 在实际应用中,应添加更健壮的错误处理机制,例如处理网络连接问题、页面不存在(404错误)、解析失败等情况。
  • 数据清洗: 抓取到的数据可能包含额外的空白字符、特殊符号或非预期的格式。使用.strip()、replace()等字符串方法进行进一步清洗是常见的步骤。
  • astype(int, errors='ignore'): 这个方法在尝试转换数据类型时非常有用,它会忽略那些无法转换为指定类型的值,保持其原始类型,从而避免程序崩溃。

6. 总结

通过本教程,我们学习了如何利用requests、BeautifulSoup和Pandas库,从复杂的网页中高效且准确地提取结构化表格数据。关键在于深入理解目标网页的HTML结构,特别是表格(

、、
)的组织方式。掌握这些技术,将使您能够自动化地获取并分析各种在线数据源,极大地提升数据处理能力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

67

2025.12.04

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

309

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

299

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1502

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

624

2023.11.24

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

0

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号