爬虫基础之BeautifulSoup---功能全面演示
0. 引言
爬虫常用技术
💡数据抓取技术
HTTP请求库(如Python的requests、aiohttp)用于发送网络请求,支持GET/POST等方法。动态页面抓取依赖无头浏览器(如Selenium、Playwright)或直接调用页面API接口。
💡解析技术
HTML解析常用BeautifulSoup、lxml,XPath和CSS选择器用于精准定位元素。JSON数据使用内置库或jsonpath处理,正则表达式(re模块)适合非结构化文本提取。
💡反反爬策略
设置随机User-Agent和IP代理池(免费/付费服务)绕过基础封锁。模拟登录需处理Cookies/Session,验证码识别可借助OCR工具(如Tesseract)或第三方打码平台。动态渲染页面通过控制浏览器行为规避检测。
💡数据存储
结构化数据存入MySQL/PostgreSQL,非结构化数据用MongoDB。分布式存储可选HBase/Cassandra,小规模数据可导出CSV/JSON文件。云存储如AWS S3适合海量资源。
💡任务调度与并发
多线程/多进程(threading、multiprocessing)提升效率,协程(asyncio)减少IO阻塞。分布式框架(Scrapy-Redis)支持跨节点协作,定时任务依赖APScheduler或系统级Cron。
💡增量爬取
通过数据库记录已抓取URL指纹(如MD5哈希),或对比页面更新时间戳。布隆过滤器高效去重,配合版本控制追踪数据变更。
💡日志与监控
日志模块(logging)记录异常和警告,Prometheus+Grafana监控爬虫健康状态。邮件/短信报警机制及时响应故障,关键指标包括请求成功率、数据增量等。
今天先学习 爬虫解析技术的BeautifulSoup 模块。
1. 概述
BeautifulSoup 是一个用于解析 HTML 和 XML 文档的 Python 库,提供了简单灵活的 API 用于遍历、搜索和修改文档树。本文件通过 10 个主要部分全面展示了其核心功能。
首先引入BeautifulSoup 模块
from bs4 import BeautifulSoup
import requests
2. 核心功能模块及代码示例
2.1 基础解析功能
-
支持从字符串解析 HTML/XML 内容
-
提供 prettify() 方法格式化输出文档结构
-
支持多种解析器,示例中使用 html.parser
# ============================= # 1. 基础功能:解析HTML/XML # ============================= print("===== 1. 基础解析功能 =====") # 从字符串解析 ,假定这是读取到页面内容 html_doc = """ <html><head><title>测试页面</title></head> <body> <p class="title"><b>小说列表</b></p> <p class="novel">科幻小说: <a href="http://example.com/scifi" class="book" id="scifi1">三体</a>, <a href="http://example.com/scifi2" class="book" id="scifi2">沙丘</a> 和 <a href="http://example.com/scifi3" class="book" id="scifi3">星际穿越</a> </p> <p class="novel">奇幻小说: <a href="http://example.com/fantasy" class="book" id="fantasy1">魔戒</a>, <a href="http://example.com/fantasy2" class="book" id="fantasy2">哈利波特</a> </p> <div class="footer">© 2023 小说网站</div> </body></html> """ soup = BeautifulSoup(html_doc, 'html.parser') print("解析后的HTML结构:") print(soup.prettify()) # 格式化输出HTML
2.2 标签选择器
-
通过标签名直接访问文档元素(如 soup.title )
-
获取标签的文本内容( string 属性)和父标签( parent 属性)
-
支持获取标签属性(如 soup.p[‘class’] )
# ============================= # 2. 标签选择器 # ============================= print("\n===== 2. 标签选择器 =====") # 获取标题标签 print("标题标签:", soup.title) print("标题文本:", soup.title.string) print("标题父标签:", soup.title.parent.name) # 获取第一个p标签 print("第一个p标签:", soup.p) print("p标签的class:", soup.p['class']) # 获取所有a标签 print("所有a标签:") for a in soup.find_all('a'): print(f" {a.string}: {a['href']}")
2.3 CSS 选择器
-
支持通过类名选择元素( soup.select(‘p.novel’) )
-
支持通过 ID 选择元素( soup.select_one(‘#scifi1’) )
-
支持层级选择( soup.select(‘body p’) )
-
支持组合选择器和属性选择器(如 a.book[id^=“scifi”] )
# ============================= # 3. CSS选择器 # ============================= print("\n===== 3. CSS选择器 =====") # 通过class选择 print("class为novel的p标签:") for p in soup.select('p.novel'): print(f" {p.text.strip()}") # 通过id选择 print("id为scifi1的a标签:", soup.select_one('#scifi1')) # 层级选择 print("body下的p标签:") for p in soup.select('body p'): print(f" {p.text.strip()}") # 组合选择 print("class为book的a标签且id以scifi开头:") for a in soup.select('a.book[id^="scifi"]'): print(f" {a.string}: {a['href']}")
2.4 标签属性操作
-
获取标签的所有属性( attrs 属性)
-
通过 get() 方法安全获取属性值
-
支持修改、添加和删除标签属性
# ============================= # 4. 标签属性操作 # ============================= print("\n===== 4. 标签属性操作 =====") a_tag = soup.find('a') print("a标签的所有属性:", a_tag.attrs) print("a标签的href属性:", a_tag.get('href')) # 修改属性 print("修改前的href:", a_tag['href']) a_tag['href'] = "http://example.com/new" print("修改后的href:", a_tag['href']) # 添加新属性 print("添加新属性前:", a_tag.attrs) a_tag['new_attr'] = 'new_value' print("添加新属性后:", a_tag.attrs) # 删除属性 del a_tag['new_attr'] print("删除属性后:", a_tag.attrs)
2.5 文本处理
-
获取标签的纯文本内容( text 属性)
-
获取特定标签的字符串内容( string 属性)
-
获取文档所有文本( get_text() 方法)
-
遍历文档中所有非空白字符串( stripped_strings 生成器)
# ============================= # 5. 文本处理 # ============================= print("\n===== 5. 文本处理 =====") # 获取标签文本 print("p标签的文本:", soup.p.text) print("p标签的字符串:", soup.p.string) # 获取多个文本 print("所有文本内容:", soup.get_text()) # 遍历所有字符串 print("遍历所有字符串:") for string in soup.stripped_strings: print(f" {string}")
2.6 导航树
-
支持访问子节点( children 属性)和后代节点
-
支持访问父节点( parent 属性)和祖先节点
-
支持访问兄弟节点( next_sibling 、 previous_sibling )
-
提供查找下一个/上一个特定标签的方法( find_next_sibling() 等)
# ============================= # 6. 导航树 # ============================= print("\n===== 6. 导航树 =====") # 子节点 print("body的子节点数量:", len(list(soup.body.children))) print("body的直接子标签:") for child in soup.body.children: if child.name: print(f" {child.name}") # 后代节点 print("body下的所有a标签数量:", len(soup.body.find_all('a'))) # 父节点 print("a标签的父节点名称:", soup.a.parent.name) print("a标签的祖父节点名称:", soup.a.parent.parent.name) # 兄弟节点 print("第一个p标签的下一个兄弟节点:", soup.p.next_sibling) print("第一个p标签的上一个兄弟节点:", soup.p.previous_sibling) # 找下一个标签节点 print("第一个p标签的下一个标签节点:", soup.p.find_next_sibling('p'))
2.7 搜索功能
-
通过标签名搜索( find_all(‘a’) )
-
通过属性搜索(如 find_all(‘a’, class_=‘book’) )
-
通过文本内容搜索,支持字符串和正则表达式
-
支持列表搜索和搜索数量限制
# ============================= # 7. 搜索功能 # ============================= print("\n===== 7. 搜索功能 =====") # 通过标签名搜索 print("所有a标签:", len(soup.find_all('a'))) # 通过属性搜索 print("class为book的a标签:", len(soup.find_all('a', class_='book'))) print("id为scifi1的标签:", soup.find_all(id='scifi1')) # 通过文本搜索 print("包含'三体'的标签:", soup.find_all(string='三体')) print("包含'小说'的标签:", soup.find_all(string=lambda text: '小说' in text)) # 正则表达式搜索 import re print("id以'scifi'开头的a标签:", soup.find_all('a', id=re.compile('^scifi'))) print("href包含'scifi'的a标签:", soup.find_all('a', href=re.compile('scifi'))) # 列表搜索 print("p标签和a标签:", len(soup.find_all(['p', 'a']))) # 限制搜索数量 print("前2个a标签:", len(soup.find_all('a', limit=2)))
2.8 修改文档树
-
创建新标签( new_tag() 方法)
-
添加标签到文档( append() 方法)
-
在指定位置插入标签( insert_before() 方法)
-
替换标签( replace_with() 方法)
-
删除标签( decompose() 方法)
# ============================= # 8. 修改文档树 # ============================= print("\n===== 8. 修改文档树 =====") # 添加标签 new_tag = soup.new_tag('a', href="http://example.com/newbook") new_tag.string = "新书" print("新创建的标签:", new_tag) soup.p.append(new_tag) print("添加标签后的p标签:", soup.p) # 插入标签 before_tag = soup.find('a', id='scifi2') insert_tag = soup.new_tag('a', href="http://example.com/insert") insert_tag.string = "插入的书" before_tag.insert_before(insert_tag) print("插入标签后相关区域:", before_tag.parent.text) # 替换标签 tag_to_replace = soup.find('a', id='fantasy1') new_tag = soup.new_tag('a', href="http://example.com/newfantasy") new_tag.string = "新奇幻" tag_to_replace.replace_with(new_tag) print("替换标签后相关区域:", new_tag.parent.text) # 删除标签 tag_to_delete = soup.find('a', id='fantasy2') tag_to_delete.decompose() print("删除标签后相关区域:", tag_to_delete.parent.text if tag_to_delete.parent else "已删除")
2.9 XML 处理
-
支持使用 XML 解析器解析 XML 文档
-
提供与 HTML 解析相似的 API 用于处理 XML 元素
# ============================= # 9. 高级功能:处理XML # ============================= print("\n===== 9. 处理XML =====") xml_doc = """ <root> <book category="fiction"> <title lang="en">Harry Potter</title> <author>J.K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="non-fiction"> <title lang="en">Learning Python</title> <author>Mark Lutz</author> <year>2013</year> <price>39.95</price> </book> </root> """ xml_soup = BeautifulSoup(xml_doc, 'xml') print("XML标题标签:", xml_soup.find('title').string) print("所有书籍作者:") for author in xml_soup.find_all('author'): print(f" {author.string}")
2.10 网页爬取实战
-
结合 requests 库获取网页内容
-
使用 BeautifulSoup 解析网页并提取信息
-
异常处理确保程序稳定性
# ============================= # 10. 实战示例:爬取网页 # ============================= print("\n===== 10. 爬取网页示例 =====") try: # 注意:这个URL只是示例 url = 'http://www.baidu.com' response = requests.get(url) response.raise_for_status() # 检查请求是否成功 web_soup = BeautifulSoup(response.text, 'html.parser') print(f"从{url}获取的标题: {web_soup.title.string}") print("页面中的链接:") for link in web_soup.find_all('a', href=True): print(f" {link.text.strip() or '无文本'}: {link['href']}") except Exception as e: print(f"爬取网页时出错: {e}") print("注:由于网络限制,此示例可能无法正常运行。")
3. 技术特点
- 简单易用 :提供直观的 API,降低解析 HTML/XML 的复杂度
- 灵活强大 :支持多种选择器和搜索方式,适应不同场景需求
- 良好的兼容性 :支持多种解析器,可处理不规范的 HTML
- 可扩展性 :易于与其他库(如 requests、re)结合使用
4. 应用场景
- 网页内容提取与分析
- 数据挖掘和爬虫开发
- HTML/XML 文档处理和转换
- 自动化测试和网页内容验证
5. 注意事项
- 在处理网络资源时需添加异常处理
- 选择合适的解析器以获得最佳性能
- 处理大型文档时需注意内存使用
- 遵守网站的 robots.txt 规则和相关法律法规
更多推荐
所有评论(0)