You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python抓取超市网站:如何自动获取分页JSON接口URL实现批量爬取?

抓取masonline.com.ar分页商品数据的解决方案

核心分析

你遇到的分页问题根源在于:手动获取的GraphQL接口URL中,分页控制参数被Base64编码后嵌入在了extensions参数里,而非随机生成的URL。具体来说,extensions中的variables字段是Base64编码的JSON,其中的from和to就是控制分页的偏移量(比如第一页是from:0, to:23,对应24个商品)。

实现步骤

  1. 解码原始variables的Base64字符串,得到分页控制的JSON结构
  2. 循环更新from和to的值(每次递增24)
  3. 将更新后的JSON重新编码为Base64,替换到接口URL的对应位置
  4. 发送请求并收集数据,直到返回的商品列表为空(表示没有更多数据)

完整代码实现

import pandas as pd
import requests
import json
import base64

# 基础接口URL模板,预留variables参数的替换位置
base_url = "https://www.masonline.com.ar/_v/segment/graphql/v1?workspace=master&maxAge=short&appsEtag=remove&domain=store&locale=es-AR&__bindingId=d62c820d-5adb-43a2-9d15-25ff4f3a6d2f&operationName=productSearchV3&variables={}&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2240b843ca1f7934d20d05d334916220a0c2cae3833d9f17bcb79cdd2185adceac%22%2C%22sender%22%3A%22vtex.store-resources%400.x%22%2C%22provider%22%3A%22vtex.search-graphql%400.x%22%7D%2C%22variables%22%3A\"{}\"%7D"

# 分页控制的原始JSON模板(解码自你提供的URL)
variables_template = {
    "hideUnavailableItems": True,
    "skuFilter": "ALL",
    "navigationBehavior": "default",
    "initialContext": "MAX_WITHOUT_INTEREST",
    "productOriginVtex": False,
    "map": "productClusterIds",
    "query": "268",
    "orderBy": "OrderByScoreDESC",
    "from": 0,
    "to": 23,
    "selectedFacets": [{"key": "productClusterIds", "value": "268"}],
    "facetsBehavior": "Static",
    "categoryTreeBehavior": "default",
    "withFacets": False,
    "variant": ""
}

# 模拟浏览器请求头,避免被拦截
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
}

all_products = []
page = 1
page_size = 24  # 每页固定24个商品

while True:
    # 更新分页偏移量
    variables_template["from"] = (page - 1) * page_size
    variables_template["to"] = page * page_size - 1
    
    # 将JSON编码为Base64
    variables_json = json.dumps(variables_template)
    variables_b64 = base64.b64encode(variables_json.encode("utf-8")).decode("utf-8")
    
    # 拼接完整请求URL
    full_url = base_url.format("{}", variables_b64)
    
    try:
        # 发送请求并解析响应
        r = requests.get(full_url, headers=headers)
        r.raise_for_status()
        data = json.loads(r.text)
        
        products = data.get("data", {}).get("productSearch", {}).get("products", [])
        if not products:
            print("无更多商品,停止抓取")
            break
        
        all_products.extend(products)
        print(f"已抓取第{page}页,共{len(products)}个商品")
        page += 1
        
    except Exception as e:
        print(f"第{page}页抓取失败:{str(e)}")
        break

# 处理并保存数据
if all_products:
    df = pd.json_normalize(all_products)
    # 保留需要的字段(与你原逻辑一致)
    columns_to_keep = ['productName', 'brand', 'priceRange.sellingPrice.lowPrice', 'link']
    df = df[columns_to_keep]
    
    df.rename(columns={
        'productName': 'Nombre',
        'brand': 'Marca',
        'priceRange.sellingPrice.lowPrice': 'Precio'
    }, inplace=True)
    df['link'] = 'https://www.masonline.com.ar/' + df['link']
    
    print("\n抓取完成,数据预览:")
    print(df.head())
    df.to_csv('masonline_products.csv', index=False, encoding='utf-8-sig')
    print("数据已保存到masonline_products.csv")
else:
    print("未抓取到任何商品")

关键说明

  • __bindingId:若该ID失效,可从普通页面的id="__NEXT_DATA__"脚本标签中提取props.pageProps.bindingId字段替换。
  • 分页逻辑:网站每页固定24个商品,因此from和to每次递增24即可覆盖所有分页。
  • 请求头:必须添加User-Agent模拟浏览器,否则容易被网站反爬机制拦截。
  • 错误处理:代码包含基础异常捕获,避免因网络波动或接口变更导致脚本直接崩溃。

为什么普通页面提取无效?

你尝试提取的script标签是网站的React hydration数据,包含大量无关渲染信息,格式复杂且解析成本高,远不如直接调用GraphQL接口高效可靠。

内容的提问来源于stack exchange,提问作者justabeginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:34:53