
在进行网页数据抓取时,我们经常会遇到网站内容并非一次性全部加载的情况。许多现代网站为了提升用户体验,会采用ajax(asynchronous javascript and xml)技术,将数据通过异步请求从服务器获取,并在用户滚动页面或点击“加载更多”按钮时动态地呈现在网页上。
对于这类动态加载的数据,传统的HTML解析库(如Python的BeautifulSoup)在仅请求初始HTML页面时,只能获取到页面首次加载时可见的部分数据。例如,当一个包含1000多条记录的表格只显示前50条,而剩余数据需要点击“加载更多”才能显示时,直接解析初始HTML将无法获取到隐藏的数据。尝试从JavaScript脚本中通过正则表达式提取数据虽然可能奏效,但这种方法通常不够健壮,因为脚本内容和结构可能随时变化。
解决动态数据抓取问题的最有效方法是绕过前端渲染,直接识别并访问网站后台提供数据的API(应用程序编程接口)。许多网站会通过RESTful API或其他形式的HTTP接口返回JSON或XML格式的结构化数据。通过浏览器开发者工具(如Chrome的Network标签页),我们可以监控页面加载过程中发出的XHR(XMLHttpRequest)请求,从而找到这些隐藏的数据接口。
一旦找到数据API,我们就可以使用HTTP请求库(如Python的requests库)直接向这些接口发送请求,获取原始的结构化数据,通常是JSON格式。这种方法具有以下显著优势:
以抓取赛马销售目录数据为例,初始页面 https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04 仅显示部分数据。通过分析网络请求,我们可以发现其完整数据是通过一个JSON接口提供的。
通过检查浏览器开发者工具的“网络”或“Network”标签页,当页面加载或点击“加载更多”时,会发现一个名为 data.json 的请求,其URL类似于 https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04/data.json。这个接口返回了所有数据,并且支持通过URL参数进行分页。
首先,我们需要请求 data.json 接口以获取关于总页数(totalPages)的信息。这通常包含在API返回的元数据中。
import requests
# 目标数据API的基础URL
base_api_url = 'https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04/data.json'
try:
# 请求API以获取分页元数据
page_metadata_response = requests.get(base_api_url)
page_metadata_response.raise_for_status() # 检查HTTP请求是否成功
page_metadata = page_metadata_response.json()
# 从元数据中提取总页数
total_pages = page_metadata['pagination']['totalPages']
print(f"总页数: {total_pages}")
except requests.exceptions.RequestException as e:
print(f"请求元数据失败: {e}")
exit()
获取到总页数后,我们可以构造一个循环,遍历每一页,并向API发送带有 page 参数的请求,从而获取每一页的数据。
import requests
import time # 引入time模块,用于添加请求间隔,避免被服务器限制
# 目标数据API的基础URL
base_api_url = 'https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04/data.json'
# ... (接上面获取 total_pages 的代码) ...
all_data_rows = []
print("开始抓取所有页面数据...")
for page_num in range(1, total_pages + 1):
try:
# 构造带有 'page' 参数的请求
response = requests.get(base_api_url, params={'page': str(page_num)})
response.raise_for_status() # 检查HTTP请求是否成功
# 解析JSON响应,提取 'rows' 字段的数据
page_data: list[dict] = response.json()['rows']
all_data_rows.extend(page_data) # 将当前页数据添加到总列表中
print(f"已抓取第 {page_num}/{total_pages} 页,包含 {len(page_data)} 条数据。")
# 为了避免对服务器造成过大压力或触发反爬机制,建议添加延时
time.sleep(0.5) # 暂停0.5秒
except requests.exceptions.RequestException as e:
print(f"抓取第 {page_num} 页失败: {e}")
# 可以选择跳过当前页或重试
print(f"\n所有页面数据抓取完成,共获取 {len(all_data_rows)} 条记录。")
# 此时,all_data_rows 列表中包含了所有页面的数据,每条数据是一个字典
# print(all_data_rows[:5]) # 打印前5条数据示例对于动态加载数据的网页抓取,直接访问底层API接口是比解析初始HTML更高效、更稳定的方法。通过分析网络请求,识别数据接口,并利用HTTP请求库直接获取JSON数据,可以轻松地抓取到网站的全部内容。掌握这种技术对于现代网页数据抓取至关重要,它能帮助我们更有效地获取所需信息,并应对日益复杂的网站结构。
以上就是掌握动态数据抓取的技巧:利用API接口高效获取分页内容的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号