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

聖光之護
发布: 2025-11-24 11:32:01
原创
200人浏览过

监测动态网页库存并发送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修图

绘蛙平台AI修图工具,支持手脚修复、商品重绘、AI扩图、AI换色

绘蛙AI修图 279
查看详情 绘蛙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.124 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,我们可以构建一个高效、实用的库存监测和通知系统。然而,持续维护和应对网站反爬机制是此类自动化工具长期运行的关键。

以上就是监测动态网页库存并发送Discord通知的Python教程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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