0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

把淘宝店铺详情搬进 MySQL:PHP 爬虫全链路实战(2025 版)

刘大雷 来源:jf_82280871 作者:jf_82280871 2025-10-16 17:31 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、为什么要自己爬店铺详情?

选品:直播团队需要「店铺评分、粉丝数、上新频率」快速筛选靠谱供应商

竞品:同一类目,对手店铺突然涨粉 10w,第一时间预警

数据训练:店铺简介 + 评分 → 做多模态情感分类

投资:提前发现「高评分+低粉丝」潜力店,谈供应链合作

官方 taobao.shop.get 需要企业资质,个人 99% 被卡;网页端「店铺主页」公开可见,走网页派依旧是最低成本方案。下面用纯 PHP 把「店铺主页 → 基础信息 → 商品列表 → 落库 → 飞书播报」一次撸完。

二、技术选型(全部开源)

wKgZPGjwuteAeFh4AABp6DI8PT0747.png

三、0 环境搭建(Linux / Win / mac 通用)

bash

# 1. 安装 PHP 8.2+ 扩展
sudo dnf install php php-cli php-curl php-dom php-mbstring php-pdo php-mysqlnd

# 2. 安装 Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

# 3. 创建项目
mkdir taobao-shop-php && cd taobao-shop-php
composer init --no-interaction --require="php:>=8.2"
composer install

四、核心流程:6 步闭环(全部代码可跑)

① 找入口:店铺主页 + 签名算法(2025-10 有效)

店铺主页:

https://shop{m}.taobao.com/shop/shop_index.htm?shop_id={shop_id}

店铺内所有商品接口(JSONP):

https://shop.m.taobao.com/shop/shopItemSearch.jsonp?shopId={shop_id}¤tPage={page}&pageSize=20&callback=jsonp123

返回:

JavaScript

jsonp123({"total":1523,"items":[{...}]})

签名逻辑(与详情页同款):

php

function sign(string $raw): string {
    return strtoupper(md5($raw));
}

调用前拼字符串:t + "&12574478&" + data + "&",其中 t 为毫秒时间戳。

② 网络层:GuzzleHttp 7 + 连接池

php

< ?php
require 'vendor/autoload.php';
use GuzzleHttpClient;
use GuzzleHttpPool;
use GuzzleHttpPsr7Request;

class ShopClient {
    private Client $http;
    private int $qps = 15; // 令牌桶

    public function __construct() {
        $this- >http = new Client([
            'timeout' => 10,
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
                'Referer' => 'https://shop.taobao.com/'
            ]
        ]);
    }

    public function fetchIndex(int $shopId): array {
        $url = "https://shop.taobao.com/shop/shop_index.htm?shop_id={$shopId}";
        $html = $this->http->get($url)->getBody()->getContents();
        return $this->parseIndex($html, $shopId);
    }

    public function fetchItems(int $shopId, int $page = 1): array {
        $this->rateLimit(); // 限速
        $callback = 'jsonp' . microtime(true);
        $data = json_encode(['shopId' => $shopId, 'currentPage' => $page], JSON_UNESCAPED_SLASHES);
        $t = (string) (microtime(true) * 1000);
        $sign = sign($t . "&12574478&" . $data . "&");

        $url = "https://shop.m.taobao.com/shop/shopItemSearch.jsonp?" . http_build_query([
            'shopId' => $shopId,
            'currentPage' => $page,
            'pageSize' => 20,
            'callback' => $callback,
            't' => $t,
            'sign' => $sign
        ]);

        $jsonp = $this->http->get($url)->getBody()->getContents();
        $json = preg_replace('/^jsonpd+(|)$/m', '', $jsonp);
        return $this->parseItems(json_decode($json, true), $shopId);
    }

    private function parseIndex(string $html, int $shopId): array {
        $doc = new DOMDocument();
        @$doc->loadHTML($html);
        $xpath = new DOMXPath($doc);
        return [
            'shop_id' => $shopId,
            'shop_name' => trim($xpath->query("//h1[@class='shop-name']")->item(0)?->nodeValue ?? ''),
            'shop_score' => trim($xpath->query("//span[@class='shop-score']")->item(0)?->nodeValue ?? ''),
            'shop_fans' => trim($xpath->query("//span[@class='shop-fans']")->item(0)?->nodeValue ?? ''),
        ];
    }

    private function parseItems(array $root, int $shopId): array {
        $items = [];
        foreach ($root['items'] ?? [] as $i) {
            $items[] = [
                'shop_id' => $shopId,
                'item_id' => $i['itemId'],
                'title' => $i['title'],
                'price' => $i['price'],
                'pic_url' => $i['picUrl'],
                'sold' => $i['sold'] ?? 0,
                'comment_count' => $i['commentCount'] ?? 0,
                'created_at' => date('Y-m-d H:i:s', $i['created'] / 1000)
            ];
        }
        return $items;
    }

    private function rateLimit(): void {
        usleep(1000000 / $this->qps); // 微秒
    }
}

③ 并发池:Guzzle Pool + 进度条

php

public function fetchAllItems(int $shopId, int $maxPage = 200): array {
    $first = $this->fetchItems($shopId, 1);
    $totalPage = min(ceil(($first['total'] ?? 0) / 20), $maxPage);

    $requests = function () use ($shopId, $totalPage) {
        for ($p = 2; $p <= $totalPage; $p++) {
            yield new Request('GET', $this- >buildItemUrl($shopId, $p));
        }
    };

    $items = [];
    $pool = new Pool($this->http, $requests(), [
        'concurrency' => 15, // 令牌桶
        'fulfilled' => function ($response, $index) use (&$items, $shopId) {
            $jsonp = $response->getBody()->getContents();
            $json = preg_replace('/^jsonpd+(|)$/m', '', $jsonp);
            $items[] = $this->parseItems(json_decode($json, true), $shopId);
        },
        'rejected' => function ($reason, $index) {
            Log::error("Page $index failed: $reason");
        },
    ]);
    $pool->promise()->wait();
    return array_merge(...$items);
}

④ 落库:Laravel Eloquent 批量 + Redis 去重

sql

CREATE TABLE tb_shop_detail (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  shop_id BIGINT NOT NULL,
  shop_name VARCHAR(100) NOT NULL,
  shop_score VARCHAR(20) NOT NULL,
  shop_fans VARCHAR(20) NOT NULL,
  item_id BIGINT NOT NULL,
  title VARCHAR(200) NOT NULL,
  price VARCHAR(30) NOT NULL,
  pic_url VARCHAR(500) NOT NULL,
  sold INT DEFAULT 0,
  comment_count INT DEFAULT 0,
  created_at DATETIME NOT NULL,
  UNIQUE KEY uk_item (item_id),
  INDEX idx_shop (shop_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

模型:

php

< ?php
namespace AppModels;

use IlluminateDatabaseEloquentModel;

class ShopDetail extends Model
{
    protected $table = 'tb_shop_detail';
    protected $fillable = [
        'shop_id','shop_name','shop_score','shop_fans',
        'item_id','title','price','pic_url','sold','comment_count','created_at'
    ];
    public $timestamps = false;
}

批量插入:

php

use IlluminateSupportFacadesDB;
use AppModelsShopDetail;

function bulkSave(array $rows): int
{
    $new = 0;
    foreach (array_chunk($rows, 1000) as $chunk) {
        $exists = Redis::command('sadd', ['item_id_set', ...array_column($chunk, 'item_id')]);
        $filtered = array_filter($chunk, fn($i) => $exists[$i['item_id']] ?? false);
        if ($filtered) {
            ShopDetail::insert($filtered);
            $new += count($filtered);
        }
    }
    return $new;
}

⑥ Docker 定时:每天 8 点飞书播报

Dockerfile

dockerfile

FROM php:8.2-cli
RUN apt-get update && apt-get install -y libcurl4-openssl-dev libssl-dev libzip-dev 
    && docker-php-ext-install pdo_mysql curl zip
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /app
COPY . .
RUN composer install --no-dev
CMD ["php","crawl.php"]

crontab

0 8 * * * docker run --rm -v /mnt/nas/shop:/app/storage taobao-shop-php

飞书推送(精简版)

php

function report(int $shopId, int $new): void {
    $body = json_encode([
        'msg_type' => 'text',
        'content'  => ['text' => "店铺 $shopId 新增 $new 条商品,已落库~"]
    ]);
    file_get_contents('https://open.feishu.cn/open-apis/bot/v2/hook/xxx', false, stream_context_create([
        'http' => ['method' => 'POST', 'header' => 'Content-Type: application/json', 'content' => $body]
    ]));
}

五、踩坑 & 反爬锦囊

JSONP 壳:正则为 ^jsonpd+(|)$,剥完再 json_decode

Referer:必须 https://shop.taobao.com/,否则 403

限速:单 IP 15 QPS 稳过,> 200/10min 必出滑块

代理池:青果云 1G ≈ 0.8 元,能跑 8 万页

重复:Redis item_id_set 秒级去重,内存省 90 %

六、结语

从店铺主页、JSONP 签名、Guzzle 并发、Eloquent 落库,到 Docker 定时 + 飞书群播报,一条完整的 PHP 闭环就打通了。
全部代码可直接扔进 PhpStorm / VSCode 跑通,改一行 shopId 就能薅任意店铺。
祝各位运营、产品、算法大佬爬得开心,爆单更开心!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • PHP
    PHP
    +关注

    关注

    0

    文章

    460

    浏览量

    28378
  • MySQL
    +关注

    关注

    1

    文章

    897

    浏览量

    29208
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    API助力,让淘宝京东拼多多店铺流量如潮水般涌来

    在电商运营中,精准的流量导入是店铺增长的核心引擎。通过开放平台的API接口,开发者可实现自动化运营,显著提升商品曝光与转化率。本文以淘宝、京东、拼多多三大平台为例,解析API技术的实战应用。 一
    的头像 发表于 12-01 14:51 103次阅读
    API助力,让<b class='flag-5'>淘宝</b>京东拼多多<b class='flag-5'>店铺</b>流量如潮水般涌来

    # 深度解析:爬虫技术获取淘宝商品详情并封装为API的流程应用

    需求。本文将深入探讨如何借助爬虫技术实现淘宝商品详情的获取,并将其高效封装为API。 一、爬虫技术核心原理与工具 1.1 爬虫运行机制 网络
    的头像 发表于 11-17 09:29 159次阅读

    淘宝平台获取店铺商品列表API接口实现详解

    ​ 在电商数据分析、店铺管理工具开发或竞品监控等场景下,通过API接口获取淘宝店铺的商品列表数据是一项常见且重要的需求。本文将介绍如何通过淘宝开放平台的API接口实现这一功能。 一、
    的头像 发表于 11-06 15:22 180次阅读
    <b class='flag-5'>淘宝</b>平台获取<b class='flag-5'>店铺</b>商品列表API接口实现详解

    淘宝商品详情API接口:电商开发的利器

    在电商蓬勃发展的今天,获取商品信息对于商家和开发者而言至关重要。淘宝作为国内最大的电商平台,其商品详情API接口为开发者提供了便捷的途径,能够高效获取海量商品信息,为各类电商应用赋能。 在成长的路上
    的头像 发表于 11-06 13:48 109次阅读

    淘宝商品详情API接口技术解析与实战应用

    随着电商行业的快速发展,数据驱动的决策模式已成为企业核心竞争力的重要组成部分。淘宝作为国内领先的电商平台,其开放平台提供的商品详情API接口为开发者提供了获取商品维度数据的通道。本文从技术实现角度
    的头像 发表于 11-04 09:50 121次阅读

    淘宝商品详情API接口(淘宝 API系列)

    在电商蓬勃发展的当下,海量的商品信息充斥着市场。对于众多电商从业者、数据分析师以及开发者而言,获取淘宝平台上丰富的商品详情数据具有极大的价值。淘宝商品详情 API 接口应运而生,它宛如
    的头像 发表于 10-20 13:32 287次阅读

    别再卡分页!淘宝量商品接口实战开发指南:从并发优化到数据完整性闭环

    淘宝店铺量商品接口实战指南:详解权限申请、分页优化、并发拉取与增量更新,结合代码实现高效稳定的数据获取,解决超时、限流、数据丢失等核心难题,助力电商数据分析避坑提效。
    的头像 发表于 09-30 10:47 326次阅读

    揭秘淘宝详情 API 接口:解锁电商数据应用新玩法

    在电商的浩瀚宇宙中,淘宝无疑是一颗璀璨的巨星。对于开发者、电商从业者来说,获取淘宝商品的详细信息是一项常见且重要的需求。而淘宝详情 API 接口,就像是一
    的头像 发表于 09-29 14:30 293次阅读

    淘宝商品详情接口(item_get)企业级解析:参数配置、签名机制与 Python 代码实战

    本文详解淘宝开放平台taobao.item_get接口对接流程,涵盖参数配置、MD5签名生成、Python企业级代码实现及高频问题排查,提供可落地的实战方案,助你高效稳定获取商品数据。
    的头像 发表于 09-26 09:13 453次阅读
    <b class='flag-5'>淘宝</b>商品<b class='flag-5'>详情</b>接口(item_get)企业级<b class='flag-5'>全</b>解析:参数配置、签名机制与 Python 代码<b class='flag-5'>实战</b>

    从 0 到 1:用 PHP 爬虫优雅地拿下京东商品详情

    PHP 语言 实现一个 可运行的京东商品爬虫 ,不仅能抓取商品标题、价格、图片、评价数,还能应对常见的反爬策略。全文附完整代码, 复制粘贴即可运行 。 一、为什么选择 PHP爬虫
    的头像 发表于 09-23 16:42 554次阅读
    从 0 到 1:用 <b class='flag-5'>PHP</b> <b class='flag-5'>爬虫</b>优雅地拿下京东商品<b class='flag-5'>详情</b>

    淘宝商品详情 API 实战:5 大策略提升店铺转化率(附签名优化代码 + 避坑指南)

    ”“差评失控” 等转化率杀手。本文结合我对接 300 + 淘宝店铺实战经验,拆解 API 如何落地到动态定价、库存预警等 5 大场景,代码做了签名优化和错误处理,新手也能直接复用,避开 90% 的调用坑。 一、
    的头像 发表于 09-15 10:53 709次阅读

    淘宝/天猫:通过商品详情API实现多店铺商品信息批量同步,确保价格、库存实时更新

    ​ 在电商运营中,管理多个淘宝或天猫店铺的商品信息(如价格和库存)是一项繁琐的任务。手动更新耗时耗力,且容易出错,导致价格不一致或库存超卖。通过淘宝/天猫开放平台提供的商品详情API,
    的头像 发表于 09-08 16:05 536次阅读
    <b class='flag-5'>淘宝</b>/天猫:通过商品<b class='flag-5'>详情</b>API实现多<b class='flag-5'>店铺</b>商品信息批量同步,确保价格、库存实时更新

    淘宝 API 实现天猫店铺商品详情页智能优化

    ​ 在竞争激烈的电商环境中,天猫店铺的商品详情页是影响用户转化率的关键因素。通过淘宝开放平台提供的API,我们可以实现智能优化,提升用户体验和销售业绩。本文将从零开始,逐步介绍如何利用淘宝
    的头像 发表于 08-13 14:35 593次阅读
    用<b class='flag-5'>淘宝</b> API 实现天猫<b class='flag-5'>店铺</b>商品<b class='flag-5'>详情</b>页智能优化

    淘宝 API 助力,天猫店铺商品上下架智能管理

    ​ 在当今电商竞争激烈的环境中,天猫店铺的商品管理效率直接影响销售业绩。手动处理商品上架和下架不仅耗时耗力,还容易出错,导致库存积压或错失销售机会。淘宝开放平台提供的 API(应用程序接口)为
    的头像 发表于 08-13 14:28 534次阅读
    <b class='flag-5'>淘宝</b> API 助力,天猫<b class='flag-5'>店铺</b>商品上下架智能管理

    揭秘淘宝 API,让天猫店铺流量来源一目了然

    ​ 在当今竞争激烈的电商环境中,天猫店铺的运营者最关心的问题之一就是:流量从哪里来?了解流量来源不仅能优化营销策略,还能提升转化率。淘宝开放平台提供的 API 接口,正是解锁这一秘密的钥匙。本文将
    的头像 发表于 08-12 14:48 587次阅读
    揭秘<b class='flag-5'>淘宝</b> API,让天猫<b class='flag-5'>店铺</b>流量来源一目了然