CodeGym /Java 课程 /Python SELF ZH /从复杂的 HTML 结构中提取数据

从复杂的 HTML 结构中提取数据

Python SELF ZH
第 34 级 , 课程 0
可用

1. 处理复杂 HTML 结构的基础

在我们开始解析复杂的 HTML 之前,理解为什么 HTML 会如此复杂是很重要的。 Web 开发者经常会用复杂的嵌套元素来组织内容,对于尝试从页面中提取数据的人来说,这可能会变成一场噩梦。但别担心——只要有好的计划和工具,你完全可以搞定!

解析 HTML 树

把 HTML 文档想象成一棵树:每个元素是一个节点,这个节点可以包含文本或其他节点。树的顶点是 html,接下来是 headbody,然后是不同的子节点。嵌套的元素位于这棵树的更深处。

简单 HTML 结构示例:

HTML

<html>
  <head>
    <title>示例</title>
  </head>
  <body>
    <div class="content">
      <h1>标题</h1>
      <p>段落 1</p>
      <p>段落 2</p>
      <div class="nested">
        <ul>
          <li>元素 1</li>
          <li>元素 2</li>
          <li><span>元素 3</span></li>
        </ul>
      </div>
    </div>
  </body>
</html>

如你所见,我们有一个 div,它的类是nested,其中包含了一个ul,而 ul 里面又有 li。这是一个嵌套元素的例子。

2. 用 BeautifulSoup 提取数据

从嵌套元素中提取数据

回顾一下 BeautifulSoup 是如何工作的。让我们用 BeautifulSoup 从 li 列表中提取文本。现在是时候成为数据侦探,从嵌套结构中获取数据了!

Python

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')
nested_items = soup.select('.nested ul li')

for item in nested_items:
    print(item.get_text())

结果:


元素 1
元素 2
元素 3

如你所见,我们使用了 select 方法和 CSS 选择器来找到 nested 类里的所有 liget_text() 方法可以直接从找到的元素中提取文本。

3. 处理多级元素

有时候数据不仅深藏在结构中,还分布在不同层级,这让提取任务变得更复杂。让我们了解一下如何从更复杂的 HTML 树中提取数据。

复杂结构示例:

HTML

<html>
  <body>
    <div class="wrapper">
      <div class="header">
        <h1>这是标题</h1>
      </div>
      <div class="content">
        <div class="article">
          <h2>文章 1</h2>
          <p>文章 1 内容</p>
        </div>
        <div class="article">
          <h2>文章 2</h2>
          <p>文章 2 内容</p>
        </div>
      </div>
      <div class="footer">
        <p>联系信息</p>
      </div>
    </div>
  </body>
</html>

从层级中提取数据

现在试着提取所有文章的标题和内容。

Python

articles = soup.select('.content .article')

for article in articles:
    title = article.find('h2').get_text()
    content = article.find('p').get_text()
    print(f'标题: {title}')
    print(f'内容: {content}\n')

预期输出:


标题: 文章 1
内容: 文章 1 内容

标题: 文章 2
内容: 文章 2 内容

我们用到了 selectfind 方法的组合。select 帮助我们找到父元素,find 则从子元素中提取信息。

4. 处理嵌套元素的特点

在研究网页时,你可能会遇到一些问题,比如多个嵌套元素有相同的类名或标签。在这些情况下,使用上下文搜索和明确的元素标识是避免错误的关键。

复杂嵌套示例:

HTML

<html>
  <body>
    <div class="container">
      <div class="item">
        <h2>编号 1</h2>
        <div class="details">详情 1</div>
      </div>
      <div class="item">
        <h2>编号 2</h2>
        <div class="details">详情 2</div>
        <div class="additional">
          <div class="info">附加信息</div>
        </div>
      </div>
    </div>
  </body>
</html>

考虑嵌套层级提取数据

为了避免混淆,应找到更具体的元素:

Python

items = soup.select('.container .item')

for item in items:
    number = item.find('h2').get_text()
    details = item.select_one('.details').get_text()
    additional_info = item.select_one('.additional .info')
    
    print(f'编号: {number}')
    print(f'详情: {details}')
    
    if additional_info:
        print(f'附加信息: {additional_info.get_text()}')
    print()

这里我们用到了 select_one 方法,该方法只返回第一个找到的元素,以避免从附加块中重复数据。

5. 实践部分和常见错误

在处理复杂的 HTML 结构时,很容易犯错,比如尝试访问不存在的元素会导致 AttributeError。为了避免这种情况,请在操作元素之前检查其是否存在。

另一个重要的事情是,不总是需要直接“硬上”提取数据。有时候,先对结构进行初步解析,使用调试输出检查中间结果是非常有帮助的。

在实际项目中,处理嵌套 HTML 结构的技能可能非常重要。这不仅适用于网页抓取,还包括测试网页接口、自动化测试,甚至用于处理复杂 API 格式化和嵌套响应的数据分析。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION