讲师中心 微信公众号
AI工具推荐 视频效率加速

监测动态网页库存并发送Discord通知的Python教程

秋浩君_2535

秋浩君_2535

发布时间:2025-11-24 11:32:01

|

308人浏览过

|

来源于php中文网

原创

监测动态网页库存并发送Discord通知的Python教程

本教程旨在指导如何使用python监测网站上特定尺寸商品的库存状态,并在库存更新时通过discord发送通知。文章将深入探讨传统网络爬虫(如beautifulsoup)在处理javascript动态加载内容时的局限性,并介绍如何利用selenium等无头浏览器工具来克服这些挑战,实现对动态生成库存信息的准确抓取与实时监控。

1. 引言:库存监测与Discord通知的需求

在电子商务日益普及的今天,许多用户希望能够实时追踪特定商品的库存状态,尤其是一些热门或限量发售的商品。当商品重新有货时,通过自动化工具及时收到通知,可以大大提高抢购成功的几率。本教程将以监测特定尺寸(例如“40码”)的商品库存为例,并演示如何将库存更新信息发送至Discord频道。

2. 初始尝试与BeautifulSoup的局限性

最初的设想是使用requests库获取网页内容,并结合BeautifulSoup进行HTML解析,以查找库存信息。以下是用户尝试的初始代码结构:

import discord
from bs4 import BeautifulSoup
import requests
import aiohttp
import asyncio

webhook_url = 'YOUR_DISCORD_WEBHOOK_URL' # 替换为你的Discord Webhook URL

async def send_webhook_message(content):
    """
    通过Discord Webhook发送消息。
    """
    async with aiohttp.ClientSession() as session:
        async with session.post(webhook_url, json={"content": content}) as response:
            if response.status == 204:
                print("Discord message sent successfully.")
            else:
                print(f"Error sending Discord message. Status code: {response.status}")

async def check_stock_initial(url, size):
    """
    初步尝试检查库存,但存在局限性。
    """
    try:
        response = requests.get(url)
        response.raise_for_status() # 检查HTTP请求是否成功
        soup = BeautifulSoup(response.text, 'html.parser')
        # 尝试查找表示库存状态的元素
        stock_element = soup.find('li', {'class': 'unselectable'})

        # 这里的逻辑是判断如果找到'unselectable'则表示无货,否则可能是有货。
        # 但这并不能精确到特定尺寸,且未考虑动态内容。
        return stock_element is None 

    except requests.RequestException as e:
        print(f"Error making request to the website: {e}")
        return False

# ... (后续的main函数和异步运行逻辑)

问题分析:

  1. 'unselectable' 与 'selectable': 在许多网站上,表示商品有货或无货的HTML元素通常会通过类名(如selectable或unselectable)来区分。unselectable通常意味着无货,而selectable则意味着有货。因此,仅仅查找unselectable并不能直接判断特定尺寸是否有货。
  2. 特定尺寸的识别: 要检查特定尺寸(如“40码”)的库存,我们需要定位到代表该尺寸的元素,并判断其状态。通常,这些尺寸选项会以
  3. 、或其他标签的形式存在,并通过title属性或文本内容来标识尺寸。
  4. 动态加载内容的核心问题: 最关键的问题在于,目标网站(如courir.com)上的库存信息,尤其是不同尺寸的可用性,是通过JavaScript在页面加载完成后动态生成的。requests库只能获取到服务器最初返回的HTML源代码,而无法执行JavaScript来渲染完整的页面。这意味着,在BeautifulSoup解析的HTML中,我们可能根本找不到那些由JavaScript生成的、包含库存信息的元素。

通过浏览器开发者工具(通常按F12打开),我们可以观察到,当页面加载完成后,表示尺寸选择的元素可能具有如下结构:

立即学习“Python免费学习笔记(深入)”;

<li class="selectable">
    <a class="swatchanchor" title="40" href="...">
        <!-- 尺寸40的显示内容 -->
    </a>
</li>

然而,这些带有selectable类和title="40"的元素,在requests获取的原始HTML中是缺失的。

Python Hardener
Python Hardener

通过完整的安全审查、代码整洁重构、健壮的错误处理、正确的日志记录以及完整的文档字符串覆盖,强化 Python 脚本。

下载

3. 解决方案:使用无头浏览器处理动态内容

为了解决JavaScript动态加载内容的问题,我们需要使用无头浏览器(Headless Browser)。无头浏览器是一种没有图形用户界面的浏览器,它可以在后台运行,模拟真实用户的行为(如加载页面、执行JavaScript、点击元素等),从而获取到完全渲染后的页面内容。

常用的无头浏览器工具有:

  • Selenium: 一个功能强大的Web自动化测试框架,支持多种浏览器(Chrome, Firefox等),并提供Python绑定。
  • Playwright: Microsoft开发的新一代Web自动化库,支持Chromium, Firefox, WebKit,性能优异。
  • Puppeteer (Node.js): Google开发的Node.js库,用于控制Chrome/Chromium。

本教程将以Selenium为例,演示如何获取动态加载的库存信息。

3.1 环境准备

  1. 安装Selenium:
    pip install selenium
  2. 下载浏览器驱动: 根据你使用的浏览器(如Chrome)版本,下载对应的WebDriver。

3.2 使用Selenium检查库存

现在,我们将重写check_stock函数,使其使用Selenium来加载和解析页面。

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException
import time # 用于等待

# 配置ChromeDriver路径 (如果未添加到系统PATH)
# service = Service(executable_path='/path/to/chromedriver') # 替换为你的chromedriver路径

async def check_stock_selenium(url, target_size):
    """
    使用Selenium检查特定尺寸的库存。
    """
    options = webdriver.ChromeOptions()
    options.add_argument('--headless') # 启用无头模式,不显示浏览器界面
    options.add_argument('--disable-gpu') # 禁用GPU加速(Linux环境下推荐)
    options.add_argument('--no-sandbox') # 禁用沙箱模式(Linux环境下推荐)
    options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124124 Safari/537.36')

    driver = None
    try:
        # 初始化WebDriver
        # driver = webdriver.Chrome(service=service, options=options) # 如果指定了service
        driver = webdriver.Chrome(options=options) # 如果chromedriver在PATH中

        driver.get(url)

        # 等待页面元素加载完成。这里等待直到表示尺寸选择的某个元素出现。
        # 通常,尺寸选择器会有一个共同的父容器或类名。
        # 我们可以等待一个通用且稳定的元素,然后查找其内部的特定尺寸。
        # 示例:等待一个class为'product-size-selector'的div出现
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, 'ul.product-size-list'))
        )

        # 查找特定尺寸的元素。
        # CSS选择器:查找 class 为 'selectable' 的 li 元素,
        # 在其内部查找 class 为 'swatchanchor' 且 title 包含目标尺寸的 a 元素。
        # 注意:这里的选择器需要根据实际网站的HTML结构进行调整。
        size_element_selector = f"li.selectable a.swatchanchor[title*='{target_size}']"

        try:
            # 尝试查找目标尺寸的“有货”元素
            size_40_available = driver.find_element(By.CSS_SELECTOR, size_element_selector)
            # 如果找到,则表示该尺寸有货
            print(f"Size {target_size} is in stock!")
            return True
        except NoSuchElementException:
            # 如果没有找到,则表示该尺寸无货
            print(f"Size {target_size} is out of stock.")
            return False

    except TimeoutException:
        print(f"Timeout waiting for page elements to load on {url}")
        return False
    except WebDriverException as e:
        print(f"WebDriver error: {e}")
        return False
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        return False
    finally:
        if driver:
            driver.quit() # 确保关闭浏览器实例

3.3 整合到异步监测循环

现在,我们可以将新的check_stock_selenium函数整合到原有的异步监测循环中。

# ... (send_webhook_message 函数保持不变)

product_data = [
    {'url': 'https://www.courir.com/fr/p/ugg-tasman-1499533.html', 'size': '40'}, # 目标尺寸改为'40'
]

async def main():
    previous_stock_status = {}  # 存储上一次的库存状态

    while True:
        result_message = ""

        for product_info in product_data:
            url = product_info['url']
            size = product_info['size']

            # 使用Selenium检查库存
            current_stock_status = await check_stock_selenium(url, size)

            # 检查库存状态是否发生变化
            if not previous_stock_status.get(url, {}).get(size, False) and current_stock_status:
                result_message += f"商品 {url} 的 {size} 码现在有货!\n"

            # 更新当前库存状态
            previous_stock_status.setdefault(url, {})[size] = current_stock_status

        if result_message: # 只有当有更新时才发送Discord消息
            print(result_message.strip())
            await send_webhook_message(result_message)
            print("已发送Discord消息。")
        else:
            print("无库存更新。")

        print("等待10分钟进行下一次检查...")
        await asyncio.sleep(600)  # 睡眠10分钟 (600秒)

if __name__ == "__main__":
    asyncio.run(main())

4. 注意事项与最佳实践

  1. 网站结构变化: 动态网站的HTML结构可能会频繁变动,导致CSS选择器失效。定期检查并更新选择器是必要的维护工作。
  2. 反爬机制: 网站可能会有反爬虫机制,如IP封锁、验证码等。
    • User-Agent: 使用真实的User-Agent头。
    • 代理IP: 考虑使用代理IP池来分散请求,避免IP被封。
    • 请求频率: 控制请求频率,模拟人类浏览行为,避免过于频繁的请求。asyncio.sleep是关键。
    • Headless检测: 有些网站能检测出无头浏览器。可以通过设置更多浏览器选项(如禁用自动化标志、伪装为真实浏览器)来规避。
  3. 错误处理: 增加更健壮的错误处理机制,例如针对NoSuchElementException、TimeoutException等。
  4. 资源消耗: 无头浏览器比requests消耗更多的系统资源(CPU和内存)。在部署时需考虑服务器性能。
  5. 异步编程: aiohttp和asyncio在处理网络请求和并发任务时非常高效,但需要确保所有I/O操作都是异步的。Selenium本身是同步的,但在async函数中调用它不会阻塞整个事件循环,只是会等待其完成。
  6. Discord Webhook安全性: 妥善保管你的Discord Webhook URL,避免泄露。

5. 总结

通过本教程,我们了解了在处理JavaScript动态加载内容的网站时,传统网络爬虫(如BeautifulSoup)的局限性。为了准确获取特定尺寸商品的库存信息,我们必须转向使用Selenium等无头浏览器工具来模拟用户行为,执行JavaScript并渲染完整页面。结合异步编程和Discord Webhook,我们可以构建一个高效、实用的库存监测和通知系统。然而,持续维护和应对网站反爬机制是此类自动化工具长期运行的关键。

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

2906

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

5959

2023.11.06

Chrome开启无痕模式
Chrome开启无痕模式

本专题整合了Chrome无痕模式开启相关内容,阅读专题下面的文章了解更多详细教程。

4247

2026.03.24

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

693

2023.11.13

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4816

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1415

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1878

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

10343

2023.08.17

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

20

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn