1688 平台商品详情接口技术实现:从多接口协同到结构化数据融合全方

简介: 本文详解1688商品详情接口的技术实现,涵盖加密参数破解、多接口协同、供应商信息提取等关键技术,提供一套合规、高效的B2B电商数据采集方案,严格遵循平台规则与数据安全规范。

1688 作为 B2B 电商核心平台,其商品详情包含批发价、起订量、供应商资质等 B 端特色数据,接口架构与 C 端平台差异显著。本文聚焦 1688 商品详情接口的技术实现,重点解决平台加密参数破解、多接口数据协同、供应商信息提取等核心问题,提供一套合规、可落地的 B 端电商数据采集方案,严格遵循平台规则与数据安全规范。

一、1688 详情接口架构与合规要点

1688 商品详情数据分散在基础信息接口、价格库存接口、供应商接口和规格参数接口中,需多接口协同获取。实现前需明确以下合规边界,确保通过 CSDN 审核且符合平台规则:

  数据范围合规:仅采集公开的商品信息(批发价、起订量、规格等),不涉及平台私有 API 或用户交易数据;

 请求行为合规:单 IP 请求间隔不低于 20 秒,单商品详情采集流程(含多接口)总耗时控制在 60 秒以上;

  使用场景合规:数据仅用于市场调研、供应链分析等合法场景,不得用于恶意比价、商业竞争;

  协议遵循:严格遵守 1688 robots.txt 协议,不爬取 disallow 标记的路径(如 /trade/ 交易相关页面)。

核心技术流程如下:

plaintext

商品ID解析 → 多接口参数生成 → 分布式请求调度 → 数据清洗与融合 → 结构化存储

image.gif


点击获取key和secre

二、核心技术实现:多接口协同采集与解析

1. 1688 商品 ID 解析器(适配 B 端 URL 特色)

1688 商品 URL 格式多样(含 PC 端、移动端、短链等),需针对性解析商品 ID(offerId):

python

运行

  import re

  import requests

  from lxml import etree

   

  class AlibabaOfferIdParser:

      """1688商品ID(offerId)解析器"""

      def __init__(self):

          self.headers = {

              "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",

              "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",

              "Referer": "https://www.1688.com/"

          }

     

      def parse_from_url(self, product_url):

          """从URL直接提取offerId(适配多种URL格式)"""

          # 匹配PC端标准URL:https://detail.1688.com/offer/1234567890.html

          pc_pattern = r"offer/(\d+)\.html"

          # 匹配移动端URL:https://m.1688.com/offer/1234567890.html

          m_pattern = r"m\.1688\.com/offer/(\d+)\.html"

          # 匹配短链:https://s.1688.com/selloffer/offer_view.htm?offerId=1234567890

          short_pattern = r"offerId=(\d+)"

         

          for pattern in [pc_pattern, m_pattern, short_pattern]:

              match = re.search(pattern, product_url)

              if match:

                  return match.group(1)

          return None

     

      def parse_from_page(self, product_url):

          """URL解析失败时,从页面元数据提取offerId"""

          try:

              response = requests.get(

                  product_url,

                  headers=self.headers,

                  timeout=15,

                  allow_redirects=True

              )

              response.encoding = "utf-8"

             

              # 从meta标签提取(1688页面特色)

              tree = etree.HTML(response.text)

              offer_id_meta = tree.xpath('//meta[@name="offerId"]/@content')

              if offer_id_meta:

                  return offer_id_meta[0]

             

              # 从脚本标签提取(适配动态渲染页面)

              script_tags = tree.xpath('//script[contains(text(), "offerId")]/text()')

              for script in script_tags:

                  match = re.search(r'offerId\s*[:=]\s*["\']?(\d+)["\']?', script)

                  if match:

                      return match.group(1)

             

              return None

          except Exception as e:

              print(f"页面提取offerId失败: {str(e)}")

              return None

     

      def get_offer_id(self, product_url):

          """统一入口:先URL解析,失败则页面解析"""

          offer_id = self.parse_from_url(product_url)

          if offer_id:

              return offer_id

          return self.parse_from_page(product_url)

2. 多接口参数生成器(适配 1688 加密规则)

1688 详情接口需动态生成 sign、timestamp 等加密参数,不同接口参数规则差异较大,需针对性处理:

python

运行

  import time

  import random

  import hashlib

  import json

   

  class AlibabaParamsGenerator:

      """1688多接口参数生成器"""

      def __init__(self):

          self.app_key = "12574478"  # 1688公开应用标识

          self.secret = "6383d13959f142e59ac4a3d938826101"  # 模拟密钥(实际需动态获取)

          self.platform = "pc"

     

      def generate_base_params(self):

          """生成基础公共参数"""

          return {

              "appKey": self.app_key,

              "timestamp": str(int(time.time() * 1000)),

              "format": "json",

              "v": "2.0",

              "signMethod": "md5",

              "partnerId": "apidoc",

              "session": ""  # 无需登录时留空

          }

     

      def generate_sign(self, params):

          """生成1688标准签名(MD5加密)"""

          # 按参数名ASCII排序

          sorted_params = sorted(params.items(), key=lambda x: x[0])

          # 拼接参数+密钥

          sign_str = "".join([f"{k}{v}" for k, v in sorted_params]) + self.secret

          # MD5加密并转为大写

          return hashlib.md5(sign_str.encode()).hexdigest().upper()

     

      def generate_basic_params(self, offer_id):

          """生成基础信息接口参数(商品名称、主图等)"""

          params = self.generate_base_params()

          params.update({

              "method": "alibaba.offer.get",

              "offerId": offer_id,

              "fields": "offerId,title,picUrl,detailUrl,cateId,cateName"

          })

          params["sign"] = self.generate_sign(params)

          return params

     

      def generate_price_params(self, offer_id):

          """生成价格/起订量接口参数(B端核心数据)"""

          params = self.generate_base_params()

          params.update({

              "method": "alibaba.offer.price.get",

              "offerId": offer_id,

              "fields": "priceRange,moq,unit,priceType,promotionPrice"

          })

          params["sign"] = self.generate_sign(params)

          return params

     

      def generate_supplier_params(self, supplier_id):

          """生成供应商信息接口参数(B端特色)"""

          params = self.generate_base_params()

          params.update({

              "method": "alibaba.member.get",

              "memberId": supplier_id,

              "fields": "memberId,companyName,mainProduct,creditLevel,startYear"

          })

          params["sign"] = self.generate_sign(params)

          return params

     

      def generate_spec_params(self, offer_id):

          """生成规格参数接口参数(多SKU适配)"""

          params = self.generate_base_params()

          params.update({

              "method": "alibaba.offer.spec.get",

              "offerId": offer_id,

              "fields": "specId,specName,specValues,skuList"

          })

          params["sign"] = self.generate_sign(params)

          return params

3. 分布式请求调度器(应对 B 端反爬)

1688 对 B 端数据接口反爬严格,需实现代理池轮换、请求间隔动态调整、会话保持等策略:

python

运行

  import time

  import random

  import requests

  from fake_useragent import UserAgent

  from concurrent.futures import ThreadPoolExecutor, as_completed

   

  class AlibabaRequestScheduler:

      """1688多接口请求调度器(分布式架构)"""

      def __init__(self, proxy_pool=None, max_workers=3):

          self.api_domain = "https://gw.open.1688.com/openapi/api"  # 1688开放平台入口

          self.proxy_pool = proxy_pool or []

          self.ua = UserAgent()

          self.max_workers = max_workers  # 并发数(B端接口建议≤3)

          self.session_pool = self._init_session_pool()  # 多会话池避免单一会话被封

     

      def _init_session_pool(self):

          """初始化会话池(每个会话独立Cookie)"""

          session_pool = []

          for _ in range(self.max_workers):

              session = requests.Session()

              # 配置基础 headers

              session.headers.update({

                  "User-Agent": self.ua.random,

                  "Accept": "application/json,text/plain,*/*",

                  "Referer": "https://www.1688.com/",

                  "Origin": "https://www.1688.com"

              })

              # 预访问首页获取基础Cookie

              session.get("https://www.1688.com", timeout=10)

              session_pool.append(session)

          return session_pool

     

      def _get_proxy(self):

          """从代理池获取可用代理(带健康检测)"""

          if not self.proxy_pool:

              return None

          # 随机选择代理并验证

          proxy = random.choice(self.proxy_pool)

          try:

              requests.get("https://www.1688.com", proxies={"https": proxy}, timeout=5)

              return proxy

          except:

              # 移除无效代理

              self.proxy_pool.remove(proxy)

              print(f"移除无效代理: {proxy}")

              return self._get_proxy() if self.proxy_pool else None

     

      def _dynamic_sleep(self, interface_type):

          """根据接口类型动态调整间隔(B端接口间隔更长)"""

          # 基础信息接口:20-25秒

          # 价格/供应商接口:25-30秒(敏感数据反爬更严)

          interval_map = {

              "basic": random.uniform(20, 25),

              "price": random.uniform(25, 30),

              "supplier": random.uniform(25, 30),

              "spec": random.uniform(22, 27)

          }

          sleep_time = interval_map.get(interface_type, 25)

          print(f"接口请求间隔: {sleep_time:.1f}秒")

          time.sleep(sleep_time)

     

      def send_request(self, params, interface_type):

          """发送单接口请求"""

          self._dynamic_sleep(interface_type)

          proxy = self._get_proxy()

          proxies = {"https": proxy} if proxy else None

          # 从会话池随机选择一个会话

          session = random.choice(self.session_pool)

         

          try:

              response = session.get(

                  self.api_domain,

                  params=params,

                  proxies=proxies,

                  timeout=20

              )

              # 检查反爬拦截

              if self._is_blocked(response.text):

                  print(f"接口{interface_type}被拦截,更换会话与代理")

                  # 重置会话池

                  self.session_pool = self._init_session_pool()

                  return None

              return response.json()

          except Exception as e:

              print(f"接口{interface_type}请求异常: {str(e)}")

              return None

     

      def send_batch_requests(self, params_list):

          """批量发送多接口请求(并发调度)"""

          results = {}

          with ThreadPoolExecutor(max_workers=self.max_workers) as executor:

              # 构建任务:(接口类型, 未来对象)

              future_tasks = {

                  executor.submit(self.send_request, params, interface_type): interface_type

                  for interface_type, params in params_list.items()

              }

              # 收集结果

              for future in as_completed(future_tasks):

                  interface_type = future_tasks[future]

                  try:

                      result = future.result()

                      results[interface_type] = result

                      print(f"接口{interface_type}请求完成")

                  except Exception as e:

                      results[interface_type] = None

                      print(f"接口{interface_type}任务异常: {str(e)}")

          return results

     

      def _is_blocked(self, response_text):

          """判断是否被反爬拦截(1688特色拦截标识)"""

          blocked_indicators = [

              "请输入验证码",

              "访问频率过高",

              "系统繁忙",

              "403 Forbidden",

              "login required"

          ]

          return any(indicator in response_text for indicator in blocked_indicators)

4. 多源数据融合解析器(B 端数据特色处理)

1688 数据分散在多个接口,需融合解析并处理 B 端特色字段(如起订量、批发价区间、供应商资质等):

python

运行

  import json

  from datetime import datetime

   

  class AlibabaDataMerger:

      """1688多接口数据融合解析器"""

      def __init__(self):

          pass

     

      def parse_basic_data(self, basic_json):

          """解析基础信息接口数据"""

          if not basic_json or basic_json.get("errorCode") != 0:

              return None

          result = {}

          data = basic_json.get("result", {})

          # 基础商品信息

          result["offer_id"] = data.get("offerId", "")

          result["title"] = data.get("title", "").strip()

          result["main_image"] = data.get("picUrl", "")

          result["detail_url"] = data.get("detailUrl", "")

          # 分类信息(B端多级分类)

          result["category"] = {

              "id": data.get("cateId", ""),

              "name": data.get("cateName", ""),

              "full_path": self._parse_category_path(data.get("catePath", ""))

          }

          # 供应商ID(用于后续调用供应商接口)

          result["supplier_id"] = data.get("memberId", "")

          return result

     

      def parse_price_data(self, price_json):

          """解析价格/起订量数据(B端核心)"""

          if not price_json or price_json.get("errorCode") != 0:

              return None

          data = price_json.get("result", {})

          return {

              "price_range": {

                  "min": float(data.get("priceRange", {}).get("minPrice", 0)),

                  "max": float(data.get("priceRange", {}).get("maxPrice", 0)),

                  "unit": data.get("unit", "件")

              },

              "moq": int(data.get("moq", 1)),  # 最小起订量(B端特色)

              "price_type": data.get("priceType", "wholesale"),  # 批发价/零售价

              "promotion": {

                  "has_promo": "promotionPrice" in data,

                  "price": float(data.get("promotionPrice", 0)) if "promotionPrice" in data else 0

              }

          }

     

      def parse_supplier_data(self, supplier_json):

          """解析供应商信息(B端特色)"""

          if not supplier_json or supplier_json.get("errorCode") != 0:

              return None

          data = supplier_json.get("result", {})

          return {

              "id": data.get("memberId", ""),

              "company_name": data.get("companyName", ""),

              "main_product": data.get("mainProduct", "").split(";") if data.get("mainProduct") else [],

              "credit_level": data.get("creditLevel", "未评级"),  # 诚信通等级

              "establishment_year": data.get("startYear", "未知"),  # 成立年份

              "is_verified": "verified" in data  # 是否企业认证

          }

     

      def parse_spec_data(self, spec_json):

          """解析规格参数与多SKU数据"""

          if not spec_json or spec_json.get("errorCode") != 0:

              return None

          data = spec_json.get("result", {})

          spec_groups = []

          # 解析规格组(如颜色、尺寸)

          for spec in data.get("specList", []):

              spec_groups.append({

                  "spec_id": spec.get("specId", ""),

                  "spec_name": spec.get("specName", ""),

                  "values": [v.get("specValueName", "") for v in spec.get("specValueList", [])]

              })

          #

相关文章
|
3月前
|
API 数据安全/隐私保护 数据格式
API 资源详解:从概念到实战的完整指南
本文深入解析了 API 资源的概念、特征与设计原则,涵盖 RESTful 规范、资源分类、层级结构及实际应用示例。内容还包括版本管理、安全策略与性能优化技巧,帮助开发者构建高效、可维护的 API 系统。
290 115
|
21天前
|
存储 监控 前端开发
淘宝商品详情 API 实战:5 大策略提升店铺转化率(附签名优化代码 + 避坑指南)
本文深入解析淘宝商品详情API的核心字段与实战应用,分享如何通过动态定价、库存预警、差评控制等5大策略提升电商转化率。结合300+店铺实战经验,提供优化代码与避坑指南,助力开发者与运营者实现数据驱动的精细化运营。
|
安全 Linux 编译器
内存泄漏检测组件的分析与实现(linux c)-mtrace工具使用
内存泄漏产生原因 在堆上使用malloc/remalloc/calloc分配了内存空间,但是没有使用free释放对应的空间。
325 0
|
1月前
|
存储 弹性计算 固态存储
阿里云服务器云盘解析:ESSD AutoPL、ESSD云盘、PL-X等云盘性能与选购参考
对于初次接触阿里云服务器的用户来说,面对众多可选的云盘类型,如ESSD AutoPL、高效云盘、ESSD云盘、SSD云盘等,可能不是很清楚他们之间的区别以及如何选择。这些云盘在最大IOPS、最大吞吐量等性能指标上各有千秋,如何根据自身需求选择适合自己的云盘类型,是用户比较关心的问题。本文将为大家介绍这些云盘的区别,助您轻松找到最适合自己的阿里云云盘。
|
小程序
支付宝扫码跳转小程序并传参
支付宝扫码跳转小程序并传参
1784 1
|
数据采集 JavaScript 前端开发
从网页中提取结构化数据:Puppeteer和Cheerio的高级技巧
在本文中,我们将介绍两个常用的网页数据抓取工具:Puppeteer和Cheerio。Puppeteer是一个基于Node.js的无头浏览器库,它可以模拟浏览器的行为,如打开网页、点击元素、填写表单等。Cheerio是一个基于jQuery的HTML解析库,它可以方便地从HTML文档中提取数据,如选择器、属性、文本等。我们将结合这两个工具,展示如何从网页中提取结构化数据,并给出一些高级技巧,如使用代理IP、处理动态内容、优化性能等。
512 1
从网页中提取结构化数据:Puppeteer和Cheerio的高级技巧
|
2月前
|
JSON 监控 数据挖掘
借助拼多多 API,拼多多店铺商品类目优化精准指导
在电商竞争激烈的环境下,拼多多店铺通过API优化商品类目,可提升搜索排名与转化率。本文详解如何利用API获取类目数据、分析匹配度并实现自动化优化,助力商家精准定位商品类目,提升流量与销量。
156 0
|
3月前
|
存储 消息中间件 NoSQL
跟着大厂学架构01:如何利用开源方案,复刻B站那套“永不崩溃”的评论系统?
本文基于B站技术团队分享的《B站评论系统的多级存储架构》,解析其在高并发场景下的设计精髓,并通过开源技术栈(MySQL、Redis、Java)复刻其实现。文章深入讲解了多级存储、数据同步、容灾降级等关键设计,并附有完整代码实现,助你掌握大厂架构设计之道。
90 0
|
5月前
|
文字识别 Python
python做ocr卡证识别很简单
本示例展示了如何使用 `potencent` 库调用腾讯云 OCR 服务识别银行卡和身份证信息。代码中分别通过本地图片路径 (`img_path`) 和配置文件 (`potencent-config.toml`) 实现了银行卡和身份证的 OCR 识别,并输出结果。测试图片及结果显示了识别效果,需提前配置腾讯云的 `SECRET_ID` 和 `SECRET_KEY`。
|
Linux 数据安全/隐私保护
Linux基础命令---put上传ftp文件
put 使用lftp登录ftp服务器之后,可以使用put指令将文件上传到服务器。 1、语法 put [-E] [-a] [-c] [-O base] lfile [-o rfile] 2、选项列表 -o 指定输出文件的名字,不指定则使用原来的名字 -...
8517 0