1688平台汇集了海量供应商与商品数据,是电商选品、供应链分析、价格监控等业务的重要信息源头。在实际项目中,获取这些数据主要有两条路:调用官方开放API和编写网页爬虫。两种方案在合规性、稳定性、开发投入和适用场景上各有优劣,选错方向可能给业务带来不必要的麻烦。本文把两种方案的核心差异、关键实现代码以及需要注意的反爬和存储细节整理出来,供有实际需求的开发者参考。


一、官方API vs 网页爬虫:核心差异对比

技术选型之前,先把两种方案在几个关键维度上的差异理清楚,这直接决定了后续的开发成本和系统稳定性。

对比维度官方API接口网页爬虫
合法合规性平台授权,完全合规,无法律风险需遵守robots.txt及平台条款,存在合规争议和封禁风险
数据质量结构化输出,字段规范、格式统一、准确性高强依赖页面DOM结构,改版即失效,容易出现字段缺失、格式脏数据
技术门槛较低,掌握HTTP请求和官方签名算法即可较高,需要熟悉爬虫框架、HTML解析、反爬对抗、甚至JS逆向和浏览器渲染
运行稳定性官方维护接口兼容性,可用性有保障需要持续跟进页面结构变化和反爬策略升级,维护成本高
使用成本部分接口有调用配额或按量计费无直接调用费用,但人力维护和反爬对抗的隐性成本不低
采集效率支持高并发批量调用,速度快受限于IP封锁、验证码、频率限制,整体吞吐量受限
数据范围仅能获取接口对外开放的字段理论可采集页面所有公开内容,自定义程度更高

简单总结:追求稳定合规、长期使用的业务场景,优先走官方API;如果接口字段实在满足不了需求,再用爬虫做补充,但要做好持续维护的心理准备。


二、官方API接入:工程化实现

1688开放平台的API是企业级采集最稳妥的选择。接入流程不复杂,关键是做好密钥管理和签名逻辑。

1. 前期准备
  • 到1688开放平台完成企业开发者认证,个人账号权限有限,规模化采集基本绕不开企业认证。

  • 创建应用,明确数据用途,审核通过后拿到 App Key 和 App Secret

  • 按需申请接口权限,比如商品搜索、商品详情、类目查询等。

2. API客户端实现

下面是一套可以直接用在生产环境里的Python客户端代码,核心处理了签名算法、公共参数封装、异常捕获和密钥的环境变量管理。

import hashlib
import time
import requests
import os
from dotenv import load_dotenv

load_dotenv()

class Ali1688APIClient:
    """1688开放平台API客户端"""

    def __init__(self):
        self.app_key = os.getenv("1688_APP_KEY")
        self.app_secret = os.getenv("1688_APP_SECRET")
        self.gateway = "https://gw.open.1688.com/openapi/param2/2.0/"

    def _build_sign(self, params: dict) -> str:
        """
        官方签名规则:
        将app_secret放在首尾,中间拼接所有参数按key升序的键值对,
        整个字符串做SHA1,结果转大写。
        """
        sorted_items = sorted(params.items())
        payload = "".join(f"{k}{v}" for k, v in sorted_items)
        raw = self.app_secret + payload + self.app_secret
        return hashlib.sha1(raw.encode("utf-8")).hexdigest().upper()

    def request(self, method: str, **biz_params) -> dict:
        """通用请求入口,自动处理公共参数和签名"""
        public_params = {
            "method": method,
            "app_key": self.app_key,
            "timestamp": str(int(time.time() * 1000)),
            "format": "json",
            "v": "2.0"
        }
        all_params = {**public_params, **biz_params}
        all_params["sign"] = self._build_sign(all_params)

        try:
            resp = requests.get(self.gateway + method, params=all_params, timeout=10)
            data = resp.json()
            if "error_response" in data:
                print(f"API错误: {data['error_response']}")
                return {}
            return data.get("result", {})
        except requests.RequestException as e:
            print(f"请求异常: {e}")
            return {}
3. 调用示例
if __name__ == "__main__":
    client = Ali1688APIClient()

    # 关键词搜索
    result = client.request("alibaba.item.search", keywords="蓝牙耳机", page_size=20)

    # 商品详情
    detail = client.request("alibaba.item.get", product_id="123456789")
4. 常用接口一览
  • alibaba.item.search:商品搜索

  • alibaba.item.get:商品详情

  • alibaba.trade.product.search4trade:店铺商品列表

  • alibaba.category.get:类目树


三、网页爬虫方案:高灵活度采集

当API字段不够用,或者需要采集非接口开放的公开数据时,爬虫可以作为补充手段。这块对技术能力要求更高,重点在于工程结构设计和反爬对抗。

1. 面向对象的爬虫架构

用抽象基类把通用能力(请求头管理、重试逻辑、随机延迟)抽离出来,具体的搜索、详情等爬虫继承基类实现各自的解析逻辑。这样做的好处是,反爬策略变更时只需要改基类,不用每个爬虫都改一遍。

import requests
import time
import random
from bs4 import BeautifulSoup
from abc import ABC, abstractmethod

class Base1688Spider(ABC):
    """1688爬虫基类:封装请求头、重试、随机延迟"""

    def __init__(self, keyword: str, max_pages: int = 5):
        self.keyword = keyword
        self.max_pages = max_pages
        self.session = requests.Session()
        self._setup_headers()

    def _setup_headers(self):
        self.session.headers.update({
            "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-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Referer": "https://www.1688.com/"
        })

    def fetch(self, url: str, retries: int = 3):
        """带重试和随机延迟的请求方法"""
        for i in range(retries):
            try:
                time.sleep(random.uniform(1.5, 3.5))
                resp = self.session.get(url, timeout=10)
                if resp.status_code == 200:
                    return resp
            except Exception as e:
                print(f"第{i+1}次重试失败: {e}")
        return None


class SearchSpider(Base1688Spider):
    """商品搜索爬虫"""

    def build_url(self, page: int = 1) -> str:
        return (
            f"https://s.1688.com/selloffer/offer_search.htm"
            f"?keywords={self.keyword}&beginPage={page}"
        )

    def parse(self, html: str) -> list:
        """多选择器兜底,降低页面结构变更的影响"""
        if not html:
            return []
        soup = BeautifulSoup(html, "html.parser")
        # 多个备选选择器,逐个尝试
        selectors = ["div.sm-offer-item", ".offer-list-item", "div[data-offer-id]"]
        items = None
        for sel in selectors:
            items = soup.select(sel)
            if items:
                break
        if not items:
            return []

        results = []
        for item in items:
            try:
                title_el = item.select_one(".title")
                price_el = item.select_one(".price")
                sales_el = item.select_one(".sale-count")
                results.append({
                    "title": title_el.text.strip() if title_el else "",
                    "price": price_el.text.strip() if price_el else "",
                    "sales": sales_el.text.strip() if sales_el else "0"
                })
            except Exception:
                continue
        return results
2. 使用示例
if __name__ == "__main__":
    spider = SearchSpider("手机壳")
    for p in range(1, 4):
        url = spider.build_url(p)
        resp = spider.fetch(url)
        if resp:
            data = spider.parse(resp.text)
            print(f"第{p}页,采集到 {len(data)} 条商品")
3. 反爬对抗要点

1688的风控比较严格,几个有效的应对思路:

  • User-Agent轮换:每次请求随机切换UA,避免请求特征过于单一。

  • 代理IP池:用付费高匿代理分散请求来源,免费代理基本扛不住,反而会加剧封禁。

  • 随机延迟:不要用固定间隔,用正态分布或指数分布的随机延迟打乱请求节奏。

  • 浏览器模拟:对于强反爬的页面,用Playwright或Selenium模拟真实用户操作,但性能开销大,只适合小批量采集。

  • 增量采集:记录上次采集的时间戳或商品ID,每次只抓新上架或变更的部分,减少无效请求。


四、数据存储与业务应用

1. 结构化存储

采集回来的数据最好做持久化处理,方便后续分析。下面是一个轻量级的存储工具,支持CSV和JSON两种格式。

import pandas as pd
import json
from datetime import datetime

class DataStorage:
    @staticmethod
    def to_csv(data: list, filename: str = None):
        if not filename:
            filename = f"1688_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        pd.DataFrame(data).to_csv(filename, index=False, encoding="utf-8-sig")
        print(f"已保存至: {filename}")

    @staticmethod
    def to_json(data: list, filename: str = None):
        if not filename:
            filename = f"1688_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(filename, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        print(f"已保存至: {filename}")
2. 典型业务场景
  • 选品分析:通过关键词搜索、类目销量排行,找到有潜力的品类和商品。

  • 竞品监控:定时抓取竞品价格和促销信息,做价格波动预警。

  • 供应链优化:积累供应商数据,搭建供应商评分模型,辅助采购决策。

  • 跨平台铺货:把1688的商品信息标准化后,同步到独立站或其他销售渠道。


五、合规与风控注意事项

  • 调用API或编写爬虫前,务必阅读并遵守1688平台的《服务条款》和robots.txt协议。

  • 严格控制请求频率,不要对平台服务器造成额外负担。

  • 采集范围限定在公开数据,不要碰用户隐私和商业机密。

  • 数据用途仅限于合法的业务分析和经营决策,不能用于数据倒卖或不正当竞争。

  • 企业场景优先考虑官方API,从根本上规避账号安全和法律风险。


六、总结

1688数据采集的技术选型,本质是在合规性、稳定性、开发成本和数据灵活性之间做权衡。建议的方案是以官方API为主,爬虫为辅助。API负责核心业务数据的稳定获取,爬虫弥补API字段覆盖不到的边缘需求。两者配合使用,既能保证系统长期可维护,又能满足业务的定制化数据诉求。无论选择哪种方案,遵守平台规则、控制好采集节奏,都是可持续运营的基本前提。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐