Web Scraping进阶:高效获取动态加载数据——直击后端JSON API

聖光之護
发布: 2025-08-02 14:10:20
原创
629人浏览过

Web Scraping进阶:高效获取动态加载数据——直击后端JSON API

本教程聚焦网络爬虫中动态加载数据的获取策略。当传统HTML解析无法获取全部数据时,我们将展示如何通过分析网站的网络请求,发现并直接调用后端JSON API。文章将提供详细的Python代码示例,指导读者高效、完整地抓取所有分页数据,并强调在爬取动态内容时的最佳实践和注意事项。

在进行网络数据抓取时,我们经常会遇到网站内容通过javascript动态加载的情况。传统的基于requests库获取html后,再使用beautifulsoup等工具解析的方式,往往只能获取到页面初始加载的部分数据,而那些需要用户滚动、点击“加载更多”按钮或等待一段时间后才显示的数据则无法通过这种方式直接获取。本文将深入探讨如何识别这类动态数据源,并提供一种更高效、更稳定的抓取策略——直接与后端json api交互。

传统HTML解析的局限性

许多现代网站为了提供更流畅的用户体验,会采用AJAX(Asynchronous JavaScript and XML)技术从服务器异步加载数据。这意味着,当您使用requests.get()获取网页HTML时,您得到的只是一个“骨架”页面,实际的数据内容是在浏览器端通过JavaScript执行后,向服务器发出额外的请求并动态填充进来的。

例如,在文章开头提到的场景中,用户尝试从racingpost.com网站抓取数据。尽管使用了BeautifulSoup并尝试通过正则表达式从script标签中提取数据,但最终只能获取到50条初始数据,而网站上实际有1000多条。这是因为剩余的数据并非直接嵌入在初始HTML中,而是通过后续的API请求获取的。直接解析HTML或依赖不稳定的正则表达式来匹配JavaScript代码中的数据,往往效率低下且容易因网站结构变化而失效。

发现数据源:直击JSON API

解决动态加载数据问题的关键在于“知其然,知其所以然”。我们需要理解数据是如何从服务器传输到客户端的。通常,这些动态数据是通过API(Application Programming Interface)以JSON或XML格式返回的。

发现这些API请求的方法是使用浏览器的开发者工具(通常按F12键打开):

  1. 打开目标网页: 访问您想要抓取数据的页面。
  2. 打开开发者工具: 切换到“Network”(网络)选项卡。
  3. 刷新页面或触发数据加载: 刷新页面,或执行导致新数据加载的操作(如点击“加载更多”按钮、滚动页面)。
  4. 过滤请求: 在“Network”选项卡中,通常会有“XHR”或“Fetch/XHR”过滤器。点击它,可以只显示异步数据请求。
  5. 检查请求: 仔细查看这些请求的URL、请求方法(GET/POST)、请求头(Headers)、请求参数(Query Parameters/Form Data)以及响应内容(Response)。

通过这种方式,我们通常可以发现一个或多个返回JSON数据的API端点。在racingpost.com的案例中,通过观察网络请求,可以发现一个清晰的JSON API:https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04/data.json。进一步分析会发现,这个API支持通过page参数进行分页,并且在不带page参数的初始请求中,会返回一个包含pagination.totalPages的元数据,这正是我们获取所有数据所需的关键信息。

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 30
查看详情 Find JSON Path Online

高效数据抓取:Python实现

一旦确定了JSON API及其分页机制,使用Python的requests库抓取数据就变得非常直接和高效。

import requests
import time # 用于添加请求延迟,避免频率过高

# 目标网站的JSON API基础URL
# 这个URL是经过网络请求分析后发现的,它直接返回结构化的数据
base_api_url = 'https://www.racingpost.com/bloodstock/sales/catalogues/5/2023-12-04/data.json'

print("--- 开始数据抓取 ---")

# 1. 获取分页元数据以确定总页数
# 首先,我们向API发送一个不带分页参数的请求,以获取总页数信息
print("正在获取分页元数据...")
try:
    # 发送GET请求到API端点
    page_metadata_response = requests.get(base_api_url)
    # 检查HTTP响应状态码,如果不是2xx,则抛出异常
    page_metadata_response.raise_for_status()
    # 将JSON响应解析为Python字典
    page_metadata = page_metadata_response.json()
    # 从元数据中提取总页数
    total_pages = page_metadata['pagination']['totalPages']
    print(f"成功获取总页数:{total_pages}")
except requests.exceptions.RequestException as e:
    # 捕获请求过程中可能发生的任何异常(如网络问题、HTTP错误)
    print(f"获取分页元数据失败: {e}")
    print("程序终止,请检查网络连接或API地址。")
    exit() # 无法获取总页数,程序无法继续执行

# 用于存储所有抓取到的数据
all_scraped_data = []

# 2. 遍历所有页面并抓取数据
# 从第一页开始,遍历到总页数
for page_num in range(1, total_pages + 1):
    print(f"正在抓取第 {page_num}/{total_pages} 页数据...")
    try:
        # 构造带页码参数的请求
        # 'params'参数会自动将字典转换为URL查询字符串,例如 '?page=1'
        response = requests.get(base_api_url, params={'page': str(page_num)})
        response.raise_for_status() # 再次检查HTTP响应状态

        # 解析当前页的JSON响应,并提取实际的数据行
        # 根据API返回的JSON结构,数据通常在一个名为 'rows' 的列表中
        current_page_data = response.json()['rows']

        # 将当前页的数据添加到总数据列表中
        all_scraped_data.extend(current_page_data)

        # 为了避免请求频率过高导致被封禁,添加短暂延迟
        time.sleep(0.5) # 建议根据网站响应和自身需求调整此值

    except requests.exceptions.RequestException as e:
        # 捕获单页请求失败的异常,打印错误信息并继续尝试下一页
        print(f"抓取第 {page_num} 页数据失败: {e}")
        continue # 跳过当前页,继续处理下一页

print(f"\n--- 数据抓取完成!共成功获取 {len(all_scraped_data)} 条数据。---")

# 示例:打印前几条抓取到的数据,以便初步验证
if all_scraped_data:
    print("\n部分抓取到的数据示例(前5条):")
    for i, item in enumerate(all_scraped_data[:5]):
        print(f"数据 {i+1}: {item}")
else:
    print("未抓取到任何数据。")

# 您可以将 all_scraped_data 保存到CSV、JSON文件或数据库中
# 例如,保存为JSON文件:
# import json
# with open('racingpost_data.json', 'w', encoding='utf-8') as f:
#     json.dump(all_scraped_data, f, ensure_ascii=False, indent=4)
# print("\n数据已保存到 racingpost_data.json")
登录后复制

注意事项与最佳实践

在进行API爬取时,除了上述代码实现,还需要注意以下几点:

  1. 网络请求分析的重要性: 掌握浏览器开发者工具(Network Tab)的使用是爬虫工程师的核心技能。它能帮助您理解网站的数据流,发现隐藏的API。
  2. 尊重网站政策: 在爬取任何网站数据之前,请务必查看其robots.txt文件(例如 https://www.racingpost.com/robots.txt)和服务条款。遵守网站的抓取规定是基本原则,避免给网站服务器造成不必要的负担。
  3. 异常处理: 在代码中加入try-except块来捕获requests可能抛出的异常(如网络连接错误、超时、HTTP错误状态码等),增强程序的健壮性。response.raise_for_status()是一个非常实用的方法,可以自动检查HTTP状态码。
  4. 速率限制与延迟: 短时间内发送大量请求可能会导致您的IP被封禁。使用time.sleep()函数在请求之间添加适当的延迟是必要的,模拟人类浏览行为。
  5. 用户代理(User-Agent)与Headers: 有些网站会检查请求头,特别是User-Agent。模拟常见的浏览器User-Agent可以减少被识别为爬虫的风险。
  6. 数据结构理解: 在解析JSON响应之前,最好先打印整个响应或部分响应,了解其内部结构,确保您能够正确地提取所需的数据。
  7. 数据存储: 抓取到的数据通常需要存储起来,可以根据需求选择CSV、JSON文件、数据库等方式。

总结

通过直接与后端JSON API交互来抓取动态加载的数据,相比于解析HTML再提取的传统方法,具有显著的优势:

  • 效率更高: 直接获取结构化数据,无需复杂的HTML解析和DOM操作。
  • 稳定性更强: API接口通常比HTML结构更稳定,不易因前端页面改版而失效。
  • 数据更清晰: JSON数据本身就是结构化的,便于直接处理和存储。

掌握这种“直击API”的爬取策略,将极大地提升您在面对复杂动态网站时的爬虫能力。始终记住,在进行网络爬取时,效率、稳定性、合法性和道德性是同等重要的考量因素。

以上就是Web Scraping进阶:高效获取动态加载数据——直击后端JSON API的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号