Beautiful Soup 是一个用于从 HTML 和 XML 文件中提取数据的 Python 库。它能够将复杂的文档解析为树形结构,并提供简单、直观的方法来遍历、搜索和修改这个树。
1. 核心对象与解析
BeautifulSoup对象: 这是整个解析文档的根对象,代表整个文档树。创建方法通常是BeautifulSoup(html_content, 'html.parser')。Tag对象: 对应 HTML/XML 中的标签(如<div>,<a>)。它拥有名称 (name)、属性 (attrs) 和内容。NavigableString对象: 代表标签内的文本内容,它是一个字符串的子类,可以直接当作字符串处理。Comment对象: 代表 HTML 中的注释内容,是NavigableString的一个特殊子类。
2. 文档遍历与导航
Beautiful Soup 提供了多种方式来遍历和导航文档树。
- 通过标签名直接访问: 可以直接使用标签名作为属性来访问第一个匹配的标签,例如
soup.div或soup.find('div')。 .contents与.children: 获取某个标签的直接子节点列表(.contents)或生成器(.children)。.descendants: 递归获取某个标签的所有子孙节点。.parent: 获取当前节点的直接父节点。.parents: 递归获取当前节点的所有父辈节点。.next_sibling与.previous_sibling: 获取同一层级的下一个或上一个节点。.next_siblings与.previous_siblings: 获取同一层级的所有后续或前序兄弟节点的生成器。
3. 搜索文档树
这是 Beautiful Soup 最强大的功能,主要通过find()和find_all()方法实现。
find_all(name, attrs, recursive, text, limit, **kwargs):- 核心搜索方法,返回所有匹配的
Tag列表。 name: 按标签名搜索(字符串、正则表达式、列表、函数或True)。attrs: 按属性搜索(字典,如{'class': 'title'})。**kwargs: 可以直接用关键字参数指定属性,如id='main'。text: 按标签内的文本内容搜索。limit: 限制返回结果的数量。recursive: 是否递归搜索子孙节点(默认为True)。
- 核心搜索方法,返回所有匹配的
find(name, attrs, recursive, text, **kwargs):- 与
find_all参数相同,但只返回第一个匹配的Tag或None。
- 与
select(css_selector):- 使用 CSS 选择器语法进行搜索,返回匹配的
Tag列表。语法强大且直观,例如soup.select('div.content > p a')。
- 使用 CSS 选择器语法进行搜索,返回匹配的
select_one(css_selector):- 使用 CSS 选择器,返回第一个匹配的
Tag或None。
- 使用 CSS 选择器,返回第一个匹配的
4. 获取与修改数据
- 获取标签名:
tag.name - 获取属性字典:
tag.attrs - 获取/修改属性值:
- 像字典一样访问:
tag['href'] - 使用
.get()方法:tag.get('class') - 修改:
tag['class'] = 'new-class' - 删除:
del tag['id']
- 像字典一样访问:
- 获取标签内的文本:
.string: 如果标签内只有一个字符串子节点,则返回它。否则返回None。.strings: 生成器,递归获取标签内所有字符串(包括子孙节点)。.get_text(separator='', strip=False): 获取标签及其所有子孙节点的文本,并用指定的separator连接。strip=True可以去除首尾空白,这是最常用和最可靠的方法。
- 修改内容:
tag.string = "新文本": 替换标签内的所有内容为单个字符串。tag.append("追加文本"): 在标签内容末尾追加一个字符串或新的Tag。tag.replace_with(new_tag_or_string): 用新的节点替换当前节点。
5. 输出与编码
prettify(): 将解析树格式化为美观的 Unicode 字符串,自动添加缩进。str()或unicode(): 获取标签的标准 HTML/XML 字符串表示。- 输出编码: Beautiful Soup 默认输出 UTF-8 编码。可以使用
soup.encode('gbk')等方法指定其他编码。
6. 解析器选择
创建BeautifulSoup对象时,第二个参数指定解析器,影响解析速度和容错能力。
'html.parser': Python 内置,速度适中,无需额外安装。'lxml':速度最快,功能强大,需要安装lxml库。'html5lib': 容错性最好,能像浏览器一样解析不规范的 HTML,但速度最慢,需要安装html5lib库。
掌握以上核心 API 足以应对绝大多数网页数据提取任务。在实践中,结合find_all的灵活参数和select的 CSS 选择器,可以高效地定位和提取所需数据。
简单示例
在给定的HTML文件中查找class="notetext"的标签,获取其自定义属性data-note的值,输出到指定的输出文件中。
frombs4importBeautifulSoupimportosdefextract_data_notes(input_html,output_txt):""" 从 HTML 文件中提取所有 class="notetext" 元素的># 1. 检查输入文件是否存在ifnotos.path.exists(input_html):print(f"错误: 文件 '{input_html}' 不存在!")returnFalsetry:# 2. 读取 HTML 文件withopen(input_html,'r',encoding='utf-8')asfile:html_content=file.read()# 3. 创建 BeautifulSoup 对象soup=BeautifulSoup(html_content,'html.parser')# 4. 查找所有 class="notetext" 的元素notetext_elements=soup.find_all(class_="notetext")# 5. 提取>=[]forelementinnotetext_elements:# 检查元素是否有>ifelement.has_attr('data-note'):note_value=element['data-note']data_notes.append(note_value)print(f"找到>{note_value}")# 6. 将结果写入文本文件withopen(output_txt,'w',encoding='utf-8')asfile:fornoteindata_notes:# 每个>file.write(note+'\n\n')# 7. 输出统计信息print(f"\n处理完成!")print(f"共找到{len(data_notes)}个>)print(f"结果已保存到:{output_txt}")returnTrueexceptExceptionase:print(f"处理过程中发生错误:{e}")returnFalse# 主程序入口if__name__=="__main__":# 设置文件路径input_file="demo.html"# 输入 HTML 文件output_file="note.txt"# 输出文本文件# 执行提取操作success=extract_data_notes(input_file,output_file)ifsuccess:print("程序执行成功!")else:print("程序执行失败!")测试文件
<!DOCTYPE html> <html> <head> <title>示例页面</title> </head> <body> <div class="container"> <p class="notetext">python extract_notes.py预期输出
程序运行后,控制台会显示:
找到>