动态网页抓取技巧:BeautifulSoup与Splinter教程
目前golang学习网上已经有很多关于文章的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《动态网页抓取技巧:BeautifulSoup与Splinter使用方法》,也希望能帮助到大家,如果阅读完后真的对你学习文章有帮助,欢迎动动手指,评论留言并分享~

在进行网页抓取时,面对重定向、动态加载内容及会话管理等复杂场景,开发者常混淆BeautifulSoup与Splinter的适用范围。本文将深入探讨这两款工具的独特功能与最佳实践,阐明它们在处理静态与动态网页时的不同策略,并指导读者如何通过浏览器开发者工具分析网络行为,从而选择合适的抓取方案,高效提取目标数据。
引言:动态网页抓取面临的挑战
随着现代网页技术的演进,许多网站不再仅仅提供静态HTML内容,而是广泛采用JavaScript进行动态渲染、处理用户交互,甚至通过多级重定向和会话管理来控制访问。这给传统的基于requests库获取HTML并结合BeautifulSoup解析的抓取方式带来了挑战。当直接使用requests访问某些URL时,可能只会得到重定向前的页面、一个免责声明页,或者因缺少必要的会话信息而无法获取到目标内容。此时,理解并选择正确的工具和策略至关重要。
Splinter与BeautifulSoup:理解各自的定位
在网页抓取领域,BeautifulSoup和Splinter(或其底层驱动Selenium)扮演着截然不同的角色,适用于不同类型的网页内容。
BeautifulSoup与Requests:静态HTML解析
requests库用于发送HTTP请求,获取网页的原始HTML内容。BeautifulSoup则是一个强大的Python库,用于从HTML或XML文件中提取数据。它们通常协同工作,适用于以下场景:
- 静态网页: 页面内容在服务器端生成,客户端直接接收到完整的HTML。
- API数据: 通过HTTP请求直接获取JSON或XML格式的数据。
- 已知URL的特定HTML片段: 即使页面有部分动态内容,但目标数据所在的HTML结构是静态且可直接通过requests获取的。
然而,当网站涉及以下情况时,单纯的requests + BeautifulSoup组合会遇到瓶颈:
- 多级重定向: 目标内容位于多次重定向后的页面。
- JavaScript动态加载: 页面内容在浏览器端通过JavaScript执行后才呈现。
- Cookie与会话管理: 网站需要特定的Cookie来维持用户会话,例如登录状态或同意免责声明。
在这种情况下,requests只能获取到重定向链条中的某个中间页面的HTML,而无法执行JavaScript或自动处理复杂的会话逻辑,导致BeautifulSoup解析时找不到目标元素,返回None或空列表。
Splinter:模拟浏览器行为
Splinter是一个高级的Python库,它封装了Selenium等浏览器自动化工具,允许开发者像真实用户一样控制浏览器(包括无头浏览器),进行页面导航、点击、填写表单、执行JavaScript等操作。它的优势在于:
- 自动处理重定向: 浏览器会自动跟随重定向,最终停留在目标页面。
- 执行JavaScript: 能够渲染动态加载的内容,使其可见并可供抓取。
- 管理Cookie和会话: 浏览器会自动接收和发送Cookie,维护会话状态。
- 模拟用户交互: 可以点击按钮、滚动页面,触发异步请求。
因此,当目标网页内容是动态生成、需要用户交互或存在复杂重定向及会话管理时,Splinter是更合适的选择。
深入分析:网站重定向与会话管理
以本教程开头提到的抓取案例为例,用户尝试抓取的网站存在典型的动态网页特性:
多级重定向问题
直接访问提供的URL https://propertyinfo.knoxcountytn.gov/Datalets/Datalet.aspx?sIndex=1&idx=1 实际上会经历一系列的HTTP重定向:
- https://propertyinfo.knoxcountytn.gov/
- https://propertyinfo.knoxcountytn.gov/search/commonsearch.aspx?mode=realprop
- https://propertyinfo.knoxcountytn.gov/Search/Disclaimer.aspx?FromUrl=../search/commonsearch.aspx?mode=realprop
最终会停留在免责声明页面。如果此时直接使用requests获取页面内容,得到的将是免责声明页面的HTML,而非包含目标数据的页面。
会话与Cookie的重要性
在免责声明页面,用户需要点击“同意”按钮才能进入实际的查询页面。这一操作通常会设置特定的Cookie,例如DISCLAIMER=1和一个会话ID (ASP.NET_SessionId)。这些Cookie对于服务器识别用户已同意条款并维持会话状态至关重要。如果后续请求不携带这些Cookie,服务器可能会再次将用户重定向回免责声明页面。
使用Splinter高效处理动态内容
对于存在重定向、JavaScript渲染和会话管理的网站,Splinter提供了一种更直观、更接近用户行为的解决方案。
Splinter的基本用法与环境配置
首先,确保安装了splinter和webdriver_manager(用于自动管理浏览器驱动):
pip install splinter webdriver_manager
然后,你可以这样初始化浏览器:
from splinter import Browser
from webdriver_manager.chrome import ChromeDriverManager
# 配置浏览器驱动,这里使用Chrome
# executable_path=ChromeDriverManager().install() 会自动下载并配置ChromeDriver
browser = Browser('chrome', executable_path=ChromeDriverManager().install(), headless=True) # headless=True 表示无头模式运行导航、交互与内容提取
使用Splinter模拟用户行为来处理重定向和免责声明:
from splinter import Browser
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup as soup
import time
# 假设目标URL是需要同意免责声明后才能访问的
initial_url = "https://propertyinfo.knoxcountytn.gov/Datalets/Datalet.aspx?sIndex=1&idx=1"
browser = None
try:
# 初始化浏览器
browser = Browser('chrome', executable_path=ChromeDriverManager().install(), headless=True)
browser.visit(initial_url)
# 等待页面加载,特别是JavaScript渲染内容
time.sleep(5) # 给予页面足够的时间加载和重定向
# 检查是否在免责声明页面,并点击同意
# 假设同意按钮的CSS选择器是 'input[name="btnAgree"]' 或其他能唯一标识的元素
# 实际选择器需要通过浏览器开发者工具检查
if browser.is_element_present_by_css('input[name="btnAgree"]', wait_time=10):
print("发现免责声明页面,点击同意...")
browser.find_by_css('input[name="btnAgree"]').click()
time.sleep(5) # 等待点击后的页面加载
# 现在应该已经到达包含目标数据的页面
print(f"当前页面URL: {browser.url}")
# 获取整个页面的HTML内容,然后可以使用BeautifulSoup进行解析
page_source = browser.html
owner_soup = soup(page_source, 'html.parser')
# 查找目标元素,例如class为'DataletData'的td标签
# 注意:原始问题中的'td', class_='DataletData' 可能并非唯一,需要更精确的选择器
# 这里假设目标数据在某个特定的td中,并且是第16个(索引15)
owner_elements = owner_soup.find_all('td', class_='DataletData')
if len(owner_elements) > 15: # 确保索引存在
target_owner_elem = owner_elements[15]
print("使用BeautifulSoup从页面源码中提取元素:")
print(target_owner_elem.prettify())
else:
print("未找到足够的'DataletData'元素或目标元素不在预期位置。")
# 或者,直接使用Splinter的API查找元素并提取内容
# 如果你知道确切的CSS选择器,Splinter可以直接返回元素对象
# 原始问题中的 browser.find_by_css('td.DataletData')[15] 返回的是Splinter的WebDriverElement对象
splinter_elem_list = browser.find_by_css('td.DataletData')
if len(splinter_elem_list) > 15:
target_splinter_elem = splinter_elem_list[15]
print("\n直接从Splinter元素中提取HTML内容:")
print(target_splinter_elem.html)
print("\n直接从Splinter元素中提取文本内容:")
print(target_splinter_elem.text)
else:
print("未通过Splinter找到足够的'DataletData'元素。")
except Exception as e:
print(f"发生错误: {e}")
finally:
if browser:
browser.quit() # 关闭浏览器获取Splinter元素的HTML内容
当browser.find_by_css('td.DataletData')[15]返回一个
# 假设 target_splinter_elem 是通过 Splinter 定位到的 WebDriverElement 对象
html_content = target_splinter_elem.html
text_content = target_splinter_elem.text
print(f"元素的HTML内容: {html_content}")
print(f"元素的文本内容: {text_content}")这样就可以直接提取所需的信息,无需再次将单个元素传递给BeautifulSoup。当然,如果需要对提取出的HTML片段进行更复杂的解析,将其传递给BeautifulSoup也是可以的:soup(html_content, 'html.parser')。
Requests与BeautifulSoup应对复杂场景的策略
尽管Splinter在处理动态内容方面更为便捷,但在某些情况下,出于性能或资源消耗的考虑,我们仍希望使用requests和BeautifulSoup。这要求我们更深入地理解HTTP协议和网站的运作机制。
开发者工具:网络请求分析利器
这是使用requests模拟复杂交互的关键。打开浏览器的开发者工具(通常按F12),切换到“Network”(网络)标签页,然后重新加载或操作页面。观察以下信息:
- 请求URL与方法: 识别所有重定向和最终目标页面的URL。
- 请求头(Request Headers): 特别是User-Agent、Referer、Cookie等,这些可能需要模拟。
- 响应头(Response Headers): 查看Set-Cookie,了解服务器设置了哪些Cookie。
- 表单数据(Form Data): 如果有点击“同意”按钮等交互,检查是否是POST请求,以及提交了哪些表单参数。
通过分析,可以发现网站的重定向链、免责声明页面的POST请求参数(如btnAgree),以及服务器设置的Cookie (ASP.NET_SessionId, DISCLAIMER=1)。
模拟HTTP请求与会话
一旦理解了网站的交互流程,就可以使用requests.Session()来模拟会话,自动处理Cookie:
import requests
from bs4 import BeautifulSoup as soup
session = requests.Session()
# 1. 访问初始URL,让session自动处理重定向并收集cookie
print("Step 1: 访问初始URL并处理重定向...")
response_initial = session.get("https://propertyinfo.knoxcountytn.gov/Datalets/Datalet.aspx?sIndex=1&idx=1")
print(f"当前URL: {response_initial.url}")
initial_soup = soup(response_initial.text, 'html.parser')
# 2. 检查是否是免责声明页面,并模拟点击“同意”
# 需要从免责声明页面中找到表单的action URL和同意按钮的name/value
# 假设通过分析,同意按钮的name是'btnAgree',且其value为空或特定值
# 并且表单提交到当前URL
if "Disclaimer.aspx" in response_initial.url:
print("Step 2: 发现免责声明,模拟点击同意...")
# 假设表单提交的URL就是当前URL,且同意按钮的name是'btnAgree'
# 实际情况可能需要从页面中解析出__VIEWSTATE, __EVENTVALIDATION等隐藏字段
form_data = {
'btnAgree': 'Agree' # 根据实际按钮的value来设置
# 可能还需要其他隐藏字段,如 __VIEWSTATE, __EVENTVALIDATION 等
# 这些需要从 initial_soup 中解析出来
}
# 尝试解析隐藏字段
for input_tag in initial_soup.find_all('input', type='hidden'):
form_data[input_tag.get('name')] = input_tag.get('value')
response_agree = session.post(response_initial.url, data=form_data)
print(f"点击同意后URL: {response_agree.url}")
# 此时 session 中应该已经包含了 DISCLAIMER=1 和新的 ASP.NET_SessionId
# 3. 现在可以访问包含目标数据的页面
# 此时 session 已经维护了必要的 cookie
# 如果点击同意后直接跳转到目标页面,则 response_agree.text 就是目标内容
# 否则,需要再次访问目标内容所在的URL
final_page_soup = soup(response_agree.text, 'html.parser')
# 在 final_page_soup 中查找目标数据
owner_elem = final_page_soup.find('td', class_='DataletData')
if owner_elem:
print("成功使用Requests和BeautifulSoup提取数据:")
print(owner_elem.prettify())
else:
print("未能通过Requests和BeautifulSoup找到目标元素。")
else:
print("当前页面不是免责声明,直接尝试解析...")
owner_elem = initial_soup.find('td', class_='DataletData')
if owner_elem:
print("成功使用Requests和BeautifulSoup提取数据:")
print(owner_elem.prettify())
else:
print("未能通过Requests和BeautifulSoup找到目标元素。")
session.close()注意事项: 使用requests模拟复杂交互的难度在于,你需要精确地复制浏览器发送的所有必要信息,包括所有隐藏的表单字段、正确的请求头和Cookie。任何微小的遗漏都可能导致失败。Postman等工具可以帮助你构建和测试这些复杂的HTTP请求。
何时选择Requests与BeautifulSoup
- 性能敏感型任务: 如果需要大规模、高并发地抓取数据,且网站结构相对简单(或复杂性可通过精确的HTTP请求模拟),requests通常比Splinter更快,因为它不需要启动和维护一个完整的浏览器实例。
- 资源受限环境: Splinter需要更多的内存和CPU资源,因为它运行一个真实的浏览器。在资源有限的环境中,requests是更好的选择。
- 学习曲线: requests和BeautifulSoup的API相对简单,易于上手,但处理动态内容时需要更深入的HTTP知识。
总结与最佳实践
- 理解工具定位: requests + BeautifulSoup适用于静态HTML解析,而Splinter(或Selenium)适用于需要浏览器渲染、执行JavaScript和处理复杂用户交互的动态网页。
- 分析网站行为: 在开始抓取前,务必使用浏览器开发者工具(Network标签页)仔细分析目标网站的HTTP请求、重定向、Cookie、表单提交和JavaScript加载行为。这是成功抓取动态内容的基石。
- 选择合适的工具:
- 如果网站内容是静态的,或者动态内容可以通过分析网络请求后精确模拟HTTP请求获取,优先使用requests + BeautifulSoup以提高效率。
- 如果网站有复杂的JavaScript渲染、多步交互(如点击、滚动)、或者难以手动模拟的会话管理,Splinter是更可靠、更便捷的选择。
- 提取Splinter元素内容: 当使用Splinter定位到元素后,直接通过.html或.text属性即可获取
终于介绍完啦!小伙伴们,这篇关于《动态网页抓取技巧:BeautifulSoup与Splinter教程》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!
JSONP优缺点及适用场景解析
- 上一篇
- JSONP优缺点及适用场景解析
- 下一篇
- 关闭Win8Defender详细步骤解析
-
- 文章 · 前端 | 42秒前 |
- 表单样式:enabled与disabled使用详解
- 406浏览 收藏
-
- 文章 · 前端 | 6分钟前 |
- ChromeDevTools调试技巧实战教程
- 358浏览 收藏
-
- 文章 · 前端 | 10分钟前 | html在线运行
- HTML在线开发流程解析与实践指南
- 155浏览 收藏
-
- 文章 · 前端 | 12分钟前 |
- CSSsticky定位技巧:多段滚动保持元素可见
- 446浏览 收藏
-
- 文章 · 前端 | 13分钟前 |
- CSS轮廓线教程:如何设置焦点提示
- 387浏览 收藏
-
- 文章 · 前端 | 21分钟前 |
- CSS外链重定向失败怎么解决?CDN加速资源加载方法
- 260浏览 收藏
-
- 文章 · 前端 | 26分钟前 |
- yield与yield*详解及使用方法
- 461浏览 收藏
-
- 文章 · 前端 | 36分钟前 |
- ReactSelect如何管理对象选项详解
- 468浏览 收藏
-
- 文章 · 前端 | 38分钟前 |
- HTML视频移动端播放优化技巧
- 270浏览 收藏
-
- 文章 · 前端 | 39分钟前 |
- void运算符的起源与应用解析
- 332浏览 收藏
-
- 文章 · 前端 | 43分钟前 |
- BOM实时音视频通信实现方法
- 421浏览 收藏
-
- 文章 · 前端 | 45分钟前 | html
- VSCode运行HTML详细步骤教程
- 196浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3226次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3440次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3470次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4580次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3849次使用
-
- JavaScript函数定义及示例详解
- 2025-05-11 502浏览
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览

