Python抓取超市网站:如何自动获取分页JSON接口URL实现批量爬取?
抓取masonline.com.ar分页商品数据的解决方案
核心分析
你遇到的分页问题根源在于:手动获取的GraphQL接口URL中,分页控制参数被Base64编码后嵌入在了extensions参数里,而非随机生成的URL。具体来说,extensions中的variables字段是Base64编码的JSON,其中的from和to就是控制分页的偏移量(比如第一页是from:0, to:23,对应24个商品)。
实现步骤
- 解码原始
variables的Base64字符串,得到分页控制的JSON结构 - 循环更新
from和to的值(每次递增24) - 将更新后的JSON重新编码为Base64,替换到接口URL的对应位置
- 发送请求并收集数据,直到返回的商品列表为空(表示没有更多数据)
完整代码实现
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
相关产品推荐
相关产品推荐

