当前位置:首页 > 技术 > 正文内容

淘宝商品详情数据采集实战指南

访客 技术 2026年10月16日 1

淘宝作为国内领先的电商平台,其反爬虫机制十分严密。要成功抓取商品详情数据,需要整合网络请求、数据解析以及应对反爬策略等多种技术手段。本指南将从环境配置、技术实现到反爬措施,提供一个全面的实操教程。

一、环境准备与配置

1. 必备工具与依赖库

  • Python 环境:推荐使用 Python 3.8 或更高版本。
  • 核心库:
    • requests:用于发送 HTTP 请求。
    • BeautifulSoup 或 lxml:用于解析 HTML 文档。
    • json:用于处理 JSON 数据。
    • re:用于正则表达式匹配。
    • selenium 或 playwright:用于处理 JavaScript 渲染的动态内容。
    • fake-useragent:用于生成随机的 User-Agent。
  • 辅助工具:
    • Chrome 浏览器及对应的 WebDriver。
    • Fiddler 或 Charles:用于网络抓包分析。
    • Postman:用于测试 API 接口。

2. 淘宝商品链接解析

淘宝商品详情页的 URL 通常包含一个唯一的商品 ID(id)。例如:

https://item.taobao.com/item.htm?id=商品ID

或其变种:

https://detail.tmall.com/item.htm?id=商品ID

这里的 商品ID 是抓取的核心标识。

二、基础采集实现(基于 requests)

1. 网络请求模块


import requests
from fake_useragent import UserAgent
import time
import random
import re
import json

# 初始化 UserAgent
user_agent_generator = UserAgent()

def fetch_taobao_item_data(item_identifier):
    """
    通过requests库获取淘宝商品详情页的HTML内容。
    :param item_identifier: 商品ID
    :return: 网页HTML内容或None
    """
    request_url = f"https://detail.tmall.com/item.htm?id={item_identifier}"
    
    # 设置请求头,模拟浏览器行为
    request_headers = {
        "User-Agent": user_agent_generator.random,
        "Referer": "https://www.taobao.com", # 简单的Referer,实际情况可能更复杂
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Connection": "keep-alive",
        # 引入Cookie可以提高成功率,需要自行获取
        "Cookie": "your_login_cookie_here" 
    }
    
    try:
        # 增加随机延迟,模拟人类行为
        time.sleep(random.uniform(1.5, 3.5))
        
        response = requests.get(request_url, headers=request_headers, timeout=15)
        
        # 检查HTTP状态码
        if response.status_code == 200:
            response.encoding = 'utf-8' # 确保正确解码
            return response.text
        else:
            print(f"请求错误:状态码 {response.status_code},URL: {request_url}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"网络请求异常:{e}")
        return None

    

2. 数据解析模块

商品详情页的数据通常嵌入在 JavaScript 变量中,可以利用正则表达式提取。


def extract_product_details(html_content):
    """
    从HTML内容中提取商品的核心信息。
    :param html_content: 商品详情页的HTML源码
    :return: 包含商品信息的字典
    """
    if not html_content:
        return {}
    
    extracted_data = {}
    try:
        # 尝试匹配 g_page_config JSON 对象
        config_match = re.search(r'g_page_config = ({.*?});', html_content, re.DOTALL)
        if config_match:
            page_config = json.loads(config_match.group(1))
            
            item_details = page_config.get('itemInfo', {}).get('item', {})
            shop_details = page_config.get('shopInfo', {})
            comment_aggregate = page_config.get('commentInfo', {}).get('commentAggregate', {})

            extracted_data = {
                "商品ID": item_details.get('id'),
                "商品名称": item_details.get('title'),
                "当前价格": item_details.get('price'),
                "原价": item_details.get('originalPrice'),
                "已售数量": item_details.get('sales'),
                "库存数量": item_details.get('stock'),
                "主图链接": item_details.get('image'),
                "店铺名称": shop_details.get('name'),
                "店铺ID": shop_details.get('id'),
                "总评论数": comment_aggregate.get('count')
            }
        else:
            # 如果 JSON 提取失败,可以尝试使用 BeautifulSoup 进行基本 HTML 标签解析
            from bs4 import BeautifulSoup
            soup = BeautifulSoup(html_content, 'lxml')
            
            title_tag = soup.find('h1', class_='tb-main-title')
            price_tag = soup.find('em', class_='tb-rmb-num')
            sales_tag = soup.find('div', class_='tb-sell-count')
            
            if title_tag: extracted_data["商品名称"] = title_tag.get_text(strip=True)
            if price_tag: extracted_data["当前价格"] = price_tag.get_text(strip=True)
            if sales_tag: extracted_data["已售数量"] = sales_tag.get_text(strip=True)
            
            print("警告:g_page_config 未找到,部分数据可能缺失,已尝试基本HTML解析。")

    except json.JSONDecodeError as e:
        print(f"JSON解析错误:{e}")
    except Exception as e:
        print(f"HTML解析异常:{e}")
        
    return extracted_data

    

三、应对反爬虫策略

淘宝的反爬机制包括但不限于:请求频率限制、User-Agent 检测、Cookie 校验、滑块验证码、动态内容加载等。

1. 使用 Selenium 模拟浏览器

对于 JavaScript 动态加载的内容或需要模拟更复杂浏览器行为的场景,Selenium 是一个强大的选择。


from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def get_product_html_selenium(item_identifier):
    """
    使用Selenium驱动Chrome浏览器获取商品详情页HTML。
    :param item_identifier: 商品ID
    :return: 网页HTML内容或None
    """
    chrome_driver_path = '/path/to/chromedriver' # 替换为你的 chromedriver 路径
    
    chrome_options = Options()
    # 启用无头模式(可选,不显示浏览器窗口)
    # chrome_options.add_argument("--headless")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument(f"user-agent={user_agent_generator.random}")
    # 绕过 webdriver 检测
    chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    
    driver = None
    try:
        service = Service(chrome_driver_path)
        driver = webdriver.Chrome(service=service, options=chrome_options)
        
        # 关键:注入脚本绕过 navigator.webdriver 检测
        driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            })
            """
        })
        
        target_url = f"https://detail.tmall.com/item.htm?id={item_identifier}"
        driver.get(target_url)
        
        # 等待关键元素加载,例如商品信息容器
        wait = WebDriverWait(driver, 15)
        wait.until(EC.presence_of_element_located((By.ID, "J_DetailMeta")))
        
        # 滚动页面以加载可能被延迟加载的内容
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(3) # 给予页面加载时间

        return driver.page_source
        
    except Exception as e:
        print(f"Selenium 操作失败:{e}")
        return None
    finally:
        if driver:
            driver.quit()

    

2. 进阶反爬策略

  • Cookie 管理:使用 requests.Session 对象来维护 Cookie,以便在多次请求中保持登录状态。
  • IP 代理:部署代理 IP 池,轮换 IP 地址以避免因请求过于频繁而被封禁。
  • 请求间隔控制:设置更长的随机延迟,并限制单位时间内的请求总量。
  • 处理验证码:对于滑块等验证码,可以考虑使用第三方打码平台或手动介入。

四、综合应用示例

以下是一个结合 requests 和 Selenium 的爬取流程示例。


# 假设已定义 get_product_html_selenium 和 extract_product_details 函数
# 并且 fetch_taobao_item_data 函数也已定义

def main_crawler_process(product_ids):
    """
    主爬虫流程,尝试使用requests,失败则回退到Selenium。
    :param product_ids: 包含商品ID的列表
    :return: 包含所有商品数据的列表
    """
    all_product_data = []
    
    for pid in product_ids:
        print(f"--- 开始处理商品ID: {pid} ---")
        page_html = None
        
        # 优先尝试 requests
        page_html = fetch_taobao_item_data(pid)
        
        if not page_html or "登录" in page_html or "验证" in page_html: # 简单判断是否需要验证或登录
            print(f"requests获取失败或内容异常,尝试使用 Selenium...")
            page_html = get_product_html_selenium(pid)
        
        if page_html:
            item_info = extract_product_details(page_html)
            if item_info and item_info.get("商品ID"):
                all_product_data.append(item_info)
                print(f"成功获取并解析: {item_info.get('商品名称', '未知名称')}")
            else:
                print(f"解析数据失败或未找到有效商品信息,商品ID: {pid}")
        else:
            print(f"两种方法均未能获取到商品页面内容,商品ID: {pid}")
            
        # 统一的延迟,降低被封风险
        time.sleep(random.uniform(4, 7)) 
            
    return all_product_data

# --- 运行示例 ---
if __name__ == "__main__":
    target_product_ids = ["678901234567", "123456789012"] # 替换为实际的商品ID
    
    collected_data = main_crawler_process(target_product_ids)
    
    # 将数据保存为JSON文件
    if collected_data:
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        filename = f"taobao_products_{timestamp}.json"
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(collected_data, f, ensure_ascii=False, indent=4)
            print(f"\n数据已成功保存至 {filename}")
        except IOError as e:
            print(f"保存文件时出错: {e}")

    

五、合规性与法律风险提示

  • 遵守平台规则:请务必阅读并遵守淘宝的服务条款和爬虫相关规定。
  • 控制爬取频率:避免过度请求,以免对淘宝服务器造成不必要的负担。
  • 数据使用规范:爬取的数据仅限个人学习和研究使用,不得用于商业目的或侵犯他人权益。
  • 关注数据时效性:商品信息(价格、库存等)变化很快,爬取的数据可能很快过时。

六、扩展与优化方向

  • 分布式爬虫:使用 Scrapy、Celery 等框架构建分布式爬虫系统,提高抓取效率。
  • 数据存储:将数据存入数据库(如 MySQL, MongoDB)以便后续分析。
  • API 封装:将爬虫逻辑封装成 API 服务,供其他应用调用。
  • 机器学习应用:分析商品数据,进行价格预测、销量趋势分析等。

淘宝的反爬策略在不断更新,请密切关注页面结构和反爬机制的变化,及时调整和优化您的爬虫代码。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。