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

加拿大药房药品爬取问题:Strength/Quantity字段重复及格式需求

解决方案:解决药品规格/数量爬取后的DataFrame重复与宽表转换问题

问题根源

你遇到的药品名称重复问题,本质是把每条规格-数量的价格条目都和基础药品信息做了拼接,导致DataFrame中每个变体对应一行重复的药品名。要实现目标宽表(以2mg、5mg、30片等为列),需要先收集所有变体数据,再通过透视转换为宽格式,最后合并基础信息。

具体实现步骤与代码

假设你已经通过Selenium获取了目标页面的驱动实例或BeautifulSoup解析后的页面对象,以下是修正后的完整逻辑:

1. 爬取药品基础信息

先一次性获取药品名称、通用名等基础信息,避免重复拼接:

from bs4 import BeautifulSoup
import pandas as pd
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# --- Selenium 页面加载(确保变体元素加载完成)---
# 假设driver是你的Selenium驱动实例
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "product-variant")))
page_source = driver.page_source
soup = BeautifulSoup(page_source, "html.parser")

# --- 提取基础信息 ---
drug_name = soup.find("h1", class_="product-name").text.strip()
generic_name = soup.find("div", class_="generic-name").text.strip()
base_info = {"药品名称": drug_name, "通用名": generic_name}

2. 收集所有规格-数量-价格组合

批量提取页面上所有变体的规格、数量和价格,存储为列表字典:

variants = []
variant_elements = soup.find_all("div", class_="product-variant")
for elem in variant_elements:
    strength = elem.find("span", class_="strength").text.strip()
    quantity = elem.find("span", class_="quantity").text.strip()
    # 处理价格,去掉$符号并转换为数值
    price_text = elem.find("span", class_="price").text.strip().replace("$", "")
    price = float(price_text) if price_text else None
    
    variants.append({
        "规格": strength,
        "数量": quantity,
        "价格": price
    })

3. 转换为目标宽表

根据你的需求,有两种宽表形式可选:

形式一:以数量为行,规格为列

适合查看同一规格下不同数量的价格对比:

# 转换为DataFrame并透视
variants_df = pd.DataFrame(variants)
pivot_df = variants_df.pivot(index="数量", columns="规格", values="价格").reset_index()

# 合并基础信息,确保药品信息不重复
pivot_df = pivot_df.assign(**base_info)
# 调整列顺序,把药品信息放在最前面
cols = ["药品名称", "通用名", "数量"] + [col for col in pivot_df.columns if col not in ["药品名称", "通用名", "数量"]]
final_df = pivot_df[cols]
形式二:以药品为单行,规格+数量为列

适合把所有价格选项整合为一行,避免药品名重复:

variants_df = pd.DataFrame(variants)
# 合并规格和数量作为列名
variants_df["规格-数量"] = variants_df["规格"] + "-" + variants_df["数量"]
# 透视为单行宽表
wide_df = variants_df.pivot_table(index=[], columns="规格-数量", values="价格").reset_index(drop=True)
# 合并基础信息
wide_df = wide_df.assign(**base_info)
# 调整列顺序
cols = ["药品名称", "通用名"] + list(wide_df.columns[:-2])
final_df = wide_df[cols]

关键注意事项

  • Selenium等待机制:必须确保所有变体元素加载完成后再提取,否则会漏爬数据
  • 数据清洗:价格字段要处理特殊符号(如$),转换为数值类型方便后续分析
  • 透视逻辑:根据实际需求选择透视的行和列,避免出现重复的药品名称条目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:30:56