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

手动构建链接可访问,用urllib调用Super-Pharm API生成下载链接失败

解决Super-Pharm价格gzip文件下载的动态Header/Cookie问题

核心思路:模拟完整浏览器会话

站点的动态Header和Cookie属于会话验证机制,硬编码固定值必然失效,必须从访问首页开始建立完整会话,自动处理Cookie和动态生成的字段。

步骤1:改用requests库(比urllib更易维护会话)

requests.Session()会自动维护会话Cookie,省去手动处理的麻烦。示例代码如下:

import requests
import re
import json

# 初始化会话,自动管理Cookie
session = requests.Session()

# 1. 访问首页,获取初始Cookie与动态参数(如CSRF Token)
home_url = "http://prices.super-pharm.co.il/"
home_res = session.get(home_url)
# 从页面meta标签提取CSRF Token(如果站点使用该验证)
csrf_token = re.search(r'<meta name="csrf-token" content="(.*?)">', home_res.text)
csrf_token = csrf_token.group(1) if csrf_token else ""

# 2. 调用第一个API,获取构建下载链接的参数
first_api_url = "替换为实际第一个API地址"
api_headers = {
    "Accept": "application/json",
    "X-CSRF-Token": csrf_token,
    "Referer": home_url,
    "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"
}
first_api_res = session.get(first_api_url, headers=api_headers)
download_params = first_api_res.json()

# 3. 调用第二个API,获取实际下载链接
second_api_url = f"替换为实际第二个API地址?param={download_params['key']}"
second_api_res = session.get(second_api_url, headers=api_headers)
actual_download_link = second_api_res.json()["download_url"]

# 4. 下载gzip文件
gzip_res = session.get(actual_download_link)
with open("super_pharm_prices.gz", "wb") as f:
    f.write(gzip_res.content)

步骤2:用浏览器开发者工具抓包分析完整流程

  1. 打开Chrome/Firefox开发者工具(F12),切换到Network标签
  2. 清空现有请求,刷新站点,跟踪从首页到两次API调用再到gzip下载的所有请求
  3. 重点分析:
    • Request Headers:区分固定字段(如User-Agent、Accept)和动态字段(如X-CSRF-Token、会话Cookie)
    • Cookie:观察Cookie的生成时机(通常是访问首页时服务器通过Set-Cookie返回)
    • 参数传递:两次API调用之间的参数依赖逻辑

步骤3:坚持用urllib的话,手动维护CookieJar

import urllib.request
import http.cookiejar
import re
import json

# 初始化CookieJar保存会话Cookie
cookie_jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookie_jar))
urllib.request.install_opener(opener)

# 1. 访问首页获取初始Cookie和动态参数
home_url = "http://prices.super-pharm.co.il/"
home_req = urllib.request.Request(home_url)
home_res = urllib.request.urlopen(home_req)
home_html = home_res.read().decode("utf-8")
csrf_token = re.search(r'<meta name="csrf-token" content="(.*?)">', home_html)
csrf_token = csrf_token.group(1) if csrf_token else ""

# 2. 第一个API请求
first_api_url = "替换为实际第一个API地址"
api_headers = {
    "Accept": "application/json",
    "X-CSRF-Token": csrf_token,
    "Referer": home_url,
    "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"
}
first_api_req = urllib.request.Request(first_api_url, headers=api_headers)
first_api_res = urllib.request.urlopen(first_api_req)
download_params = json.loads(first_api_res.read().decode("utf-8"))

# 3. 第二个API请求获取下载链接
second_api_url = f"替换为实际第二个API地址?param={download_params['key']}"
second_api_req = urllib.request.Request(second_api_url, headers=api_headers)
second_api_res = urllib.request.urlopen(second_api_req)
actual_link = json.loads(second_api_res.read().decode("utf-8"))["download_url"]

# 4. 下载gzip文件
download_req = urllib.request.Request(actual_link, headers=api_headers)
download_res = urllib.request.urlopen(download_req)
with open("super_pharm_prices.gz", "wb") as f:
    f.write(download_res.read())

关键注意事项

  • 绝不硬编码Cookie/Header:动态字段必须从会话中实时获取,Cookie由会话自动维护,CSRF Token从页面提取
  • 严格遵循浏览器请求顺序:必须先访问首页,再调用API,直接请求API会被服务器拒绝
  • 使用真实浏览器的User-Agent:避免被识别为爬虫
  • 确认API请求方式:部分API为POST而非GET,抓包时注意核对Request Method

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:43:39