跳到内容

如何在Python中将HTML转换为文本?

这是一篇 2000 多字的博客文章,内容是“如何在 Python 中将 HTML 转换为文本?”:

HTML 是在网络上存储和显示数据的重要格式。当网页抓取时,我们通常只想从 HTML 页面中提取可见的文本内容。在这篇文章中,我将探索在 Python 中将 HTML 转换为干净文本的不同技术。

为什么要将 HTML 转换为文本?

您可能想要剥离 HTML 标签并仅提取文本的主要原因有几个:

  • 简化抓取的内容 – 抓取网页时,HTML 通常包含许多我们不需要的额外标记和元素,例如导航链接。提取正文使内容更易于分析和使用。

  • 删除格式 – HTML 应用视觉格式和布局。对于情感分析等许多应用程序,我们只需要不带任何格式的文本内容。

  • 以文本格式存储 – 仅从 HTML 中提取文本非常有用,因此可以将其存储为简单的格式,例如文本文件或数据库文本字段。这会删除所有庞大的 HTML 标记。

  • 可读性 – 原始 HTML 人类很难阅读和解释。转换为文本使其更具可读性。

  • 无障碍 – 视力障碍用户使用的屏幕阅读器更容易访问纯文本内容。

  • 搜索引擎索引 – 搜索引擎主要分析和索引页面的可见文本内容。将 HTML 转换为文本可以帮助分析内容,就像搜索引擎如何看待它一样。

总之,从 HTML 中提取文本对于抓取、分析、存储和可访问性很有用。接下来的部分将介绍在 Python 中实现此目的的不同方法。

使用 BeautifulSoup 剥离 HTML 标签

Beautiful Soup 是一个流行的 Python 库,用于网页抓取和解析 HTML。我们可以使用它相当轻松地从 HTML 中提取文本。

最简单的方法是调用 get_text() BeautifulSoup 对象或从解析的 HTML 中选择的元素上的方法。例如:

from bs4 import BeautifulSoup

html = """<p>Here is a paragraph with <a href="http://example.com">a link</a>."""

soup = BeautifulSoup(html, "html.parser")

text = soup.get_text()
print(text)

# Output: Here is a paragraph with a link.

这会去除所有 HTML 标签并返回包含可见文本的字符串。

有一点需要注意的是 get_text() 默认情况下也会将多个连续的空白字符压缩为一个空格。经过 strip=False 保留空白,如换行符和额外空格:

text = soup.get_text(strip=False) 
print(text)

# Output: 
# 
# Here is a paragraph with  
#            a link.

要仅从 HTML 的一部分中提取文本,请调用 get_text() 在一个元素而不是整个文档上:

el = soup.select_one("p")
text = el.get_text()
print(text)

# Output: Here is a paragraph with a link.

需要注意的是 get_text() 仍将包含嵌套在子元素(如链接)内的任何文本。也要把它们去掉,传递一个 recursive=False 参数:

text = el.get_text(recursive=False)
print(text) 

# Output: Here is a paragraph with 

所以有了BeautifulSoup我们就可以轻松使用 get_text() 从 HTML 中提取可见文本。

使用 lxml 提取文本

xml文件 是另一个流行的用于解析 XML 和 HTML 的 Python 库。我们也可以用它来提取文本。

来自 lxml HTMLParser 元素,调用 text_content() 获取文本的方法:

from lxml.html import fromstring, HTMLParser

html = """<p>Here is a paragraph with <a href="http://example.com">a link</a>.</p>"""

tree = fromstring(html, parser=HTMLParser())

text = tree.text_content() 
print(text)

# Output: Here is a paragraph with a link.

这将递归地提取所有文本,包括子元素中的文本。要排除子项中的文本,请传递 children=False 参数:

text = tree.text_content(children=False)
print(text)

# Output: Here is a paragraph with 

因此lxml还提供了一种简单的方法来剥离HTML并仅获取文本内容。

常用表达

基于正则表达式的方法也可用于删除 HTML 标签。这涉及使用模式来匹配所有 HTML 标签,并用替换来替换它们:

import re

html = """<p>Here is a paragraph with <a href="http://example.com">a link</a>.</p>"""

clean = re.sub(r"<[^>]*>", "", html) 
print(clean)

# Output: Here is a paragraph with a link.

正则表达式 r"<[^>]*>" 火柴 < 后面跟任何东西除了 > 一次或多次,然后 >。 该 re.sub() 调用会删除这些匹配项,从而有效地删除所有 HTML 标签。

还可以处理 XML 命名空间和自结束标签:

clean = re.sub(r"<[^>]+>", "", html)

这是一种快速、简单的基于正则表达式的方法,用于去除所有 HTML 标签。尽管它不提供与 BeautifulSoup 和 lxml 等特定 HTML 解析库相同的控制和简单性。

处理编码

网页可以采用各种文本格式进行编码,例如 ASCII、UTF-8 或 ISO-8859-1。当抓取页面时,我们想要检测编码并正确解码为 Unicode 文本。

chardet 库可以自动为我们检测编码:

import chardet

html = b"<p>Hello world</p>"

encoding = chardet.detect(html)["encoding"]

if encoding:
    html = html.decode(encoding)
else:
    html = html.decode("utf-8") 

print(html)

然后,我们可以在解析和提取文本之前将 HTML 字节显式解码为 Unicode 字符串。

将 HTML 转换为文本时,应在解析之前先处理编码,以避免编码错误。

完整的 HTML 到文本示例

下面是一个示例,将所涵盖的步骤放在一起,以稳健地从 HTML 中提取文本:

from bs4 import BeautifulSoup
import chardet
import re

def html_to_text(html):
    # Detect encoding
    encoding = chardet.detect(html)["encoding"] 

    if encoding:
        html = html.decode(encoding)
    else:
        html = html.decode("utf-8")

    # Remove tags
    clean = re.sub(r"<[^>]+>", "", html)

    # Extract text
    soup = BeautifulSoup(clean, "html.parser")
    text = soup.get_text(strip=True)

    return text

html = """<p>Here is a paragraph with <a href="http://example.com">a link</a>.</p>"""

print(html_to_text(html))

# Output: Here is a paragraph with a link.

它处理编码检测、剥离标签以及在可重用函数中提取文本。

还有一些 Python 库,例如 提取物 封装了一些将各种文件格式转换为文本的功能。

转换 HTML 实体

我们可能遇到的另一个问题是 HTML 使用字符实体,例如  & 而不是字面字符。

我们可以使用 html.unescape() Python 标准中的函数 html库 将实体转换回字符:

import html

text = " Bread & Butter"

print(html.unescape(text))

# Output: Bread & Butter 

这可以在从 HTML 中提取文本之前或之后完成。

处理 JavaScript

上述技术的局限性是它们仅从初始 HTML 中提取可见文本。任何由 JavaScript 动态添加的文本都不会被捕获。

要执行 JavaScript 并呈现全文,我们需要使用无头浏览器,例如 or 剧作家:

from playwright.sync_api import sync_playwright

html = """<p>Hello</p><script>document.body.innerHTML += "<p>World</p>";</script>"""

with sync_playwright() as p:
    browser = p.webkit.launch()
    page = browser.new_page()
    page.content = html
    text = page.content()
    browser.close()

print(text)    
# Output: <p>Hello</p><p>World</p>

这里 Playwright 用于加载页面并执行 JavaScript,使我们能够提取完整的文本。

因此,对于具有大量 JS 操作的页面,如果我们需要完整渲染的文本,则可能需要浏览器自动化工具。

总结

在 Python 中将 HTML 转换为纯文本有以下几种主要技术:

  • 使用 get_text() 来自 美丽汤
  • 提取内容 text_content() 在 lxml 中
  • 使用正则表达式删除标签
  • 在解析之前解码任何编码
  • 处理 HTML 实体 html.unescape()
  • 如果需要执行 JavaScript,请使用无头浏览器

将 HTML 转换为文本对于简化抓取的内容、分析文本而不是标记、提高可读性和可访问性、通过搜索引擎建立索引以及以轻量级格式存储非常有用。

我希望这篇文章能够为使用 Python 从 HTML 中提取文本的主要方法提供全面的指南!如果您有任何其他有用的技术,请告诉我。

标签:

加入谈话

您的电邮地址不会被公开。 必填带 *