You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

爬取DataFrame与Excel转换DataFrame按名称匹配时ValueError问题的解决方案咨询

解决DataFrame匹配时的ValueError问题及实现商品价格监控逻辑

你遇到的ValueError完全是因为直接对布尔Series做真值判断导致的——df1["Item Name"].str.contains(x)返回的是一个包含True/False的Series,而if语句需要的是单个布尔值,Python没法确定你要判断这个Series里的所有元素还是任意元素,所以抛出了这个模糊性错误。

针对你的需求(匹配相同商品名称并执行价格分析),用Pandas的merge关联两个DataFrame是更高效且符合Pandas idiomatic的方式,比循环遍历要简洁得多,也能避免这类错误。下面是重构后的代码和思路:

核心思路

  1. 用merge将新爬取的df和历史Excel的df1按Item Name做内连接,直接得到所有名称匹配的商品行对。
  2. 针对每一对匹配的行,处理不同的价格可用场景(原价/折扣价是否为"Not Available"),计算价格差异。
  3. 更新df1中的价格(如果新价格更便宜),同时收集价格下降的记录到cheap_cheap。
  4. 处理df中未在df1出现的商品(可选,根据你的需求决定是否添加到历史数据)。

修改后的代码

import pandas as pd
import asyncio

# 假设pricecompare是你已经定义好的价格比较函数,比如返回新价格减旧价格的数值
def pricecompare(new_price, old_price):
    # 这里需要把字符串价格转成数值,比如去掉货币符号、逗号等
    new = float(new_price.replace('$', '').replace(',', ''))
    old = float(old_price.replace('$', '').replace(',', ''))
    return new - old

def pricemonitor(category):
    global cheap_cheap
    # 执行爬取,得到新的df(这里假设searching函数返回爬取后的DataFrame)
    df = asyncio.run(searching(category))
    # 读取历史Excel数据
    df1 = pd.read_excel(f"C:\\Users\\N\\PycharmProjects\\pythonProject\\Scrapped results\\{category}.xlsx")
    
    # 初始化价格下降记录DataFrame
    if 'cheap_cheap' not in globals():
        cheap_cheap = pd.DataFrame(columns=["Item Name", "New Price", "Old Price", "Amount difference"])
    
    # 1. 关联两个DataFrame,找到名称匹配的商品
    merged = pd.merge(df, df1, on="Item Name", suffixes=('_new', '_old'), how='inner')
    
    # 2. 遍历匹配的行,处理价格比较和更新
    for idx, row in merged.iterrows():
        item_name = row["Item Name"]
        # 定义各价格变量
        new_item_price = row["Item Price_new"]
        new_disc_price = row["Discounted Price_new"]
        old_item_price = row["Item Price_old"]
        old_disc_price = row["Discounted Price_old"]
        
        cheaper = None
        new_price = None
        old_price = None
        
        # 场景1:原价和折扣价都可用
        if (new_item_price != "Not Available" and new_disc_price != "Not Available" and
            old_item_price != "Not Available" and old_disc_price != "Not Available"):
            cheaper = pricecompare(new_disc_price, old_disc_price)
            new_price = new_disc_price
            old_price = old_disc_price
        # 场景2:只有原价可用
        elif new_item_price != "Not Available" and old_item_price != "Not Available":
            cheaper = pricecompare(new_item_price, old_item_price)
            new_price = new_item_price
            old_price = old_item_price
        # 场景3:只有折扣价可用
        elif new_disc_price != "Not Available" and old_disc_price != "Not Available":
            cheaper = pricecompare(new_disc_price, old_disc_price)
            new_price = new_disc_price
            old_price = old_disc_price
        else:
            # 无可用价格,跳过
            continue
        
        # 如果新价格更便宜(cheaper为负,因为new - old < 0)
        if cheaper < 0:
            # 记录价格变化
            cheap_row = pd.DataFrame({
                "Item Name": [item_name],
                "New Price": [new_price],
                "Old Price": [old_price],
                "Amount difference": [cheaper]
            })
            cheap_cheap = pd.concat([cheap_cheap, cheap_row], ignore_index=True)
            
            # 更新df1中的对应价格
            if new_price == new_disc_price:
                df1.loc[df1["Item Name"] == item_name, "Discounted Price"] = new_disc_price
            else:
                df1.loc[df1["Item Name"] == item_name, "Item Price"] = new_item_price
    
    # 可选:把df中未在df1出现的商品添加到df1中(如果需要扩充历史数据)
    new_items = df[~df["Item Name"].isin(df1["Item Name"])]
    df1 = pd.concat([df1, new_items], ignore_index=True)
    
    # 保存更新后的df1回Excel
    df1.to_excel(f"C:\\Users\\N\\PycharmProjects\\pythonProject\\Scrapped results\\{category}.xlsx", index=False)

关键改进点

  • 避免循环遍历单个值:用merge直接关联匹配的商品,比你原来的循环更高效,尤其是数据量大的时候。
  • 修复变量名冲突:原来的函数参数x和循环变量x重名,现在改成category避免混淆。
  • 明确价格场景处理:把不同的价格可用情况拆分成清晰的条件分支,逻辑更易读。
  • 正确更新df1:用df1.loc[df1["Item Name"] == item_name, ...]精准定位要更新的行,避免批量赋值错误。
  • 初始化全局变量:添加了cheap_cheap的初始化逻辑,防止第一次运行时变量未定义。

另外,还要注意pricecompare函数需要正确处理字符串格式的价格(比如去掉货币符号、千位分隔符),如果你的价格格式不同,需要调整这个函数的逻辑。

内容的提问来源于stack exchange,提问作者NZH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:04:05