爬取Ace Hardware API遍历分页报未授权如何解决
Ace Hardware门店接口爬取401错误解决方案
报错原因
浏览器可正常访问接口、requests请求返回UNAUTHORIZED,核心原因是请求头缺失必填鉴权字段。报错提示要求的application access token并非需要单独申请的商业API密钥,是站点给普通前端访客生成的临时访问令牌,浏览器发起请求时会自动携带,仅传User-Agent的请求会被反向代理识别为非浏览器流量直接拦截。
现有代码还存在两处逻辑问题:
- 生成了存储全量页码的
url_list但未遍历调用,仅请求了不带页码参数的基础URL - 对已解析为字典格式的响应数据执行
json.dumps()转为字符串,后续pd.json_normalize()无法正确处理字符串格式的JSON内容。
无API密钥爬取实现方法
不需要注册开发者账号、不需要申请官方接口权限,按以下步骤调整即可正常采集:
- 补全请求头
在浏览器中打开任意一页接口地址,按F12调出开发者工具,切换到「网络」面板后刷新页面,找到对应locations的请求,复制它的请求头参数,重点补全以下校验字段:核心必填字段是
Referer和带x-vol-前缀的参数,其中x-vol-access-token就是报错要求的鉴权令牌,直接从浏览器请求头复制即可,有效期通常为数天。
参考请求头格式:headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'en-US,en;q=0.9', 'Referer': 'https://www.acehardware.com/store-directory', 'x-vol-site-context': 'SP', 'x-vol-access-token': '替换为从浏览器请求头复制的对应值', 'x-vol-locale': 'en-US', 'x-vol-currency': 'USD' } - 修正遍历与解析逻辑
不要硬编码总页数,先请求第一页拿到接口返回的真实总页数,再逐页遍历采集,同时增加延时避免触发频率限制,修正后的完整代码如下:import requests import pandas as pd import time base_url = 'https://www.acehardware.com/api/commerce/storefront/locationUsageTypes/SP/locations?page={}' # 替换为补全后的headers headers = {} all_data = [] # 拉取第一页数据,获取总页数 first_resp = requests.get(base_url.format(0), headers=headers, timeout=15) first_resp.raise_for_status() first_page = first_resp.json() total_pages = first_page['pageCount'] all_data.extend(first_page['items']) print(f'总页数:{total_pages},第0页采集完成') # 遍历剩余页码 for page_num in range(1, total_pages): try: resp = requests.get(base_url.format(page_num), headers=headers, timeout=15) resp.raise_for_status() page_data = resp.json() all_data.extend(page_data['items']) print(f'第{page_num}页采集完成,剩余{total_pages - page_num -1}页') # 增加1秒延时,降低请求频率 time.sleep(1) except Exception as e: print(f'第{page_num}页采集失败,错误信息:{e},3秒后重试') time.sleep(3) # 单次重试 try: resp = requests.get(base_url.format(page_num), headers=headers, timeout=15) page_data = resp.json() all_data.extend(page_data['items']) except: print(f'第{page_num}页重试失败,跳过') continue # 直接解析字典列表,无需额外转字符串 df = pd.json_normalize(all_data) df.to_csv('ace_hardware_locations.csv', index=False, encoding='utf-8-sig') - 注意事项
- 若采集过程中再次出现401报错,重新从浏览器复制最新的
x-vol-access-token替换即可,该令牌会定期更新 - 不要删除延时逻辑、不要开高并发,站点有频率控制,请求过快会被临时封禁IP
- 采集到的门店数据如果用于商业用途请遵守站点相关条款
内容的提问来源于stack exchange,提问作者Zane Cantrell
相关产品推荐
相关产品推荐

