python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python BeautifulSoup解析HTML

Python使用BeautifulSoup库处理HTML的简单教学

作者:detayun

BeautifulSoup4是Python常用HTML/XML解析库,能修复不规范网页并构建DOM树,本文将带你快速上手BeautifulSoup4,从安装到实战,掌握find、select等核心API,轻松提取文本、属性和修改DOM,希望对大家有所帮助

前言

在爬虫开发中,拿到网页HTML源码后,需要完成解析、提取文本、修改节点、过滤标签、HTML转换等工作。BeautifulSoup4(简称bs4)是Python最常用的HTML/XML解析库,它可以把杂乱不规范的网页HTML修复为DOM树,相比手写正则解析HTML,稳定性更强,容错能力高,适合处理真实互联网上各式各样的脏网页。

注意:BeautifulSoup本身只是解析封装,底层需要依赖解析器,常用两种:

  1. html.parser:Python内置,无需额外安装,容错一般;
  2. lxml:速度快,容错强,生产环境优先推荐,需要pip安装。

一、安装依赖

# 安装bs4
pip install beautifulsoup4
# 推荐同时安装lxml解析器(性能更好)
pip install lxml

二、基础使用:加载HTML

从字符串加载

from bs4 import BeautifulSoup

html_doc = """
<html>
<head><title>测试页面</title></head>
<body>
    <div class="item">
        <h2>标题1</h2>
        <p class="desc">这是描述文本</p>
    </div>
</body>
</html>
"""

# 使用lxml解析器
soup = BeautifulSoup(html_doc, "lxml")
# 格式化输出html
print(soup.prettify())

结合requests爬虫,解析网页响应

import requests
from bs4 import BeautifulSoup

resp = requests.get("[https://example.com](https://example.com)")
# 直接传入文本
soup = BeautifulSoup(resp.text, "lxml")

小提示:遇到UTF‑8 BOM网页,如果乱码,可以先处理bytes再解码:

content = resp.content
if content.startswith(b"\xef\xbb\xbf"):
    content = content[3:]
soup = BeautifulSoup(content.decode("utf‑8‑sig", errors="replace"), "lxml")

三、节点查找提取数据(核心API)

find():查找第一个匹配节点

# 根据标签名
title_tag = soup.find("title")
print(title_tag.text)

# 根据class类名
div_tag = soup.find("div", class_="item")

# 根据id
soup.find(id="main")

class是Python关键字,bs4中使用参数名 class_ 带下划线。

find_all():查找全部匹配节点,返回列表

# 获取所有p标签
p_list = soup.find_all("p")

# 获取所有class=desc的p标签
p_desc_list = soup.find_all("p", class_="desc")

# 限制返回最多2条结果
soup.find_all("p", class_="desc", limit=2)

CSS选择器 select / select_one

熟悉css选择器的话优先用这个,写起来简洁。

# .代表class,#代表id
item_div = soup.select_one(".item")
all_p = soup.select(".item p")

for p in all_p:
    print(p.get_text(strip=True))

四、获取文本、属性

获取节点文本

tag = soup.find("p", class_="desc")

# .text 获取所有拼接文本,包含子节点文字
print(tag.text)

# get_text(),strip=True自动去除前后空白、换行
print(tag.get_text(strip=True))

# 分割文本,使用分隔符拼接子节点文本
print(tag.get_text(strip=True, separator=" "))

获取标签属性

a_tag = soup.find("a")
href = a_tag.get("href")   # 推荐,属性不存在返回None,不会抛异常
# 不推荐:a_tag["href"] 不存在属性直接抛KeyError

# 获取全部属性字典
attr_dict = a_tag.attrs
print(attr_dict)

五、修改HTML DOM(增删改节点)

适合场景:修改网页片段、转换HTML、清理无用标签。

创建新节点

from bs4 import BeautifulSoup, NavigableString, Tag

new_tag = soup.new_tag("td")
new_tag.string = "单元格内容"

添加子节点

div = soup.find("div", class_="item")
div.append(new_tag)  # 末尾追加节点

删除节点

tag = soup.find("script")
if tag:
    tag.decompose() # 彻底移除节点以及内部所有内容

替换节点内容

tag.string = "新的文字内容"

输出处理完成后的HTML字符串

out_html = soup.prettify()          # 格式化带换行缩进
raw_html = str(soup)                # 紧凑输出

六、实战示例1:清理网页,移除script、style

爬虫预处理网页,清除js、css标签,减少干扰:

def clean_html(html_str: str):
    soup = BeautifulSoup(html_str, "lxml")
    # 删除不需要的标签
    for bad in soup(["script", "style", "noscript"]):
        bad.decompose()
    return soup.prettify()

七、实战示例2:div伪表格转table(对应你之前的业务场景)

把bootstrap div栅格伪表格,用bs4实现转为原生table,和之前lxml版本效果一致

from bs4 import BeautifulSoup

def bs_div_to_table(html_str: str) -> str:
    soup = BeautifulSoup(html_str, "lxml")
    table = soup.new_tag("table", border="1", cellpadding="6", cellspacing="0", style="border‑collapse:collapse;width:100%;")
    thead = soup.new_tag("thead")
    tbody = soup.new_tag("tbody")
    table.append(thead)
    table.append(tbody)

    # 解析表头
    header_box = soup.select_one('div.row.structure .boxs')
    if header_box:
        tr_head = soup.new_tag("tr")
        for col_div in header_box.select("> div"):
            txt = col_div.get_text(strip=True)
            th = soup.new_tag("th")
            th.string = txt
            tr_head.append(th)
        thead.append(tr_head)

    # 解析所有数据行
    rows = soup.select("div.structurewords")
    for row_div in rows:
        tr = soup.new_tag("tr")
        for cell_div in row_div.select("> div"):
            cell_txt = cell_div.get_text(strip=True)
            td = soup.new_tag("td")
            td.string = cell_txt
            tr.append(td)
        tbody.append(tr)

    full_soup = BeautifulSoup("""<!DOCTYPE html>
<html lang="zh‑CN">
<head><meta charset="UTF‑8"><title>表格预览</title></head>
<body></body>
</html>""", "lxml")
    full_soup.body.append(table)
    return full_soup.prettify()

八、BeautifulSoup常见坑点

  1. 不要用正则代替解析库:HTML标签嵌套、属性顺序变化,正则极易解析失败;
  2. find()找不到返回None,调用.text会抛AttributeError,要做判空;
  3. 获取属性优先用.get("xxx"),不要直接下标["xxx"],防止属性缺失抛异常;
  4. prettify()会增加换行缩进,如果入库存储不需要格式化,直接用str(soup)
  5. 网页不规范、残缺标签,lxml解析器修复能力比内置html.parser更强;
  6. bs4适合解析操作DOM,大规模抓取解析性能弱于lxml,追求速度优先选lxml。

小结

BeautifulSoup4 封装简单友好,适合大多数爬虫HTML解析、清洗、修改DOM场景。

对比:lxml性能更高,适合高并发爬虫;bs4语法更通俗易懂,适合快速开发、调试。

到此这篇关于Python使用BeautifulSoup库处理HTML的简单教学的文章就介绍到这了,更多相关Python BeautifulSoup解析HTML内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文