0

0

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

聖光之護

聖光之護

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

|

268人浏览过

|

来源于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码”)的库存,我们需要定位到代表该尺寸的元素,并判断其状态。通常,这些尺寸选项会以<li>、<a>或其他标签的形式存在,并通过title属性或文本内容来标识尺寸。
  3. 动态加载内容的核心问题: 最关键的问题在于,目标网站(如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中是缺失的。

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

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

AI小聚
AI小聚

一站式多功能AIGC创作平台,支持AI绘画、AI视频、AI聊天、AI音乐

下载

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

  • 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工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

1059

2023.08.11

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

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

841

2023.11.06

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

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

293

2023.11.13

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

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

531

2023.06.20

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

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

576

2023.07.28

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

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

760

2023.08.03

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

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

6235

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

492

2023.09.01

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

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

精品课程

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

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 42.7万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号