# %% [markdown] cell-5e351e7966a3
## 🕐请从本地上传一个用电商记插件采集的淘宝搜索2025新版结果(含综合排序和销量排序)的Excel文件。[下载示例](https://www.dianshangji.cn/u/user5344/cfiles/browse/index?fid=3)
# %%--- [html] cell-a5b79fdf3c10
# properties:
#   run_on_load: true
#   locked: true
#   top_hidden: true
# ---%%
<input class="btn btn-primary" type="file" id="fileInput"/> 
# %%--- [javascript] cell-184eb2fa1fde
# properties:
#   run_on_load: true
# ---%%
await waitChange("fileInput");
# %%--- [python] cell-45f12e7b9d96
# properties:
#   run_on_load: true
# ---%%
import pyodide, os, requests, js, json, micropip, xlrd
await micropip.install('et_xmlfile-2.0.0-py3-none-any.whl')
await micropip.install('openpyxl-3.1.5-py2.py3-none-any.whl')
os.chdir('/')
# %%--- [javascript] cell-6522f6fedafd
# properties:
#   run_on_load: true
# ---%%
await initFileInputs("fileInput", {".xlsx": "/taobaosearchraw.xlsx"});
# %%--- [python] cell-50bbd749f8a1
# properties:
#   run_on_load: true
#   top_hidden: true
# ---%%
import pandas as pd

def process_taobao_data():
  print("开始读取内存中的Excel文件……")
  df = pd.read_excel('/taobaosearchraw.xlsx', skiprows=0)
  
  # 打印前5条记录
  print(df.head(5))
  
  # 代码片段1
  # 假设 df 是已经加载的数据
  # 检查商品ID是否有重复记录
  if df['商品ID'].duplicated().any():
      print("存在重复的商品ID记录,正在去除重复条目...")
      # 去除重复的商品ID条目,只保留第一次出现的记录
      df = df.drop_duplicates(subset=['商品ID'], keep='first')
  else:
      print("没有重复的商品ID记录。")
  
  # 代码片段2
  import re
  
  # 定义一个函数来处理“月销量”字段
  def clean_month_sales(sales_str):
      if pd.isna(sales_str):
          return None
      
      sales_str = str(sales_str).strip()
      
      if "本月行业热销" in sales_str:
          return 1000
      elif "万+" in sales_str:
          match = re.search(r'(\d+)', sales_str)
          if match:
              return int(match.group(1)) * 10000
      elif "+人收货" in sales_str:
          match = re.search(r'(\d+)', sales_str)
          if match:
              return int(match.group(1))
      
      try:
          return int(sales_str)
      except ValueError:
          return None
  
  # 应用函数到“月销量”列
  df['月销量'] = df['月销量'].apply(clean_month_sales)
  
  # 代码片段3
  # 筛选出“价格”小于等于10000元的记录
  df = df[df['价格'] <= 10000]
  print("筛选出“价格”小于等于10000元的记录")
  
  # 筛选出“月销量”大于等于0元的记录
  df = df[df['月销量'] >= 0]
  print("筛选出“月销量”大于等于0的记录")
  
  # 打印前5条记录以检查结果
  print(df.head(5))
  
  print("有效记录总数:", len(df))

  df.to_excel('/淘宝搜索结果.xlsx', sheet_name='销量', index=False)

process_taobao_data()
# %%--- [javascript] cell-a7694943954c
# properties:
#   run_on_load: true
# ---%%
await initHome(true);
await viewFile('淘宝搜索结果.xlsx')
# %% [markdown] cell-d4de1bcd39b2
## 🕑数据清洗与预处理
在进行数据分析之前,首先需要对采集到的数据进行清洗和预处理。数据清洗的过程包括去除缺失值、异常值处理、格式标准化等步骤。由于淘宝平台的数据可能存在一定的噪声(如商品标题的重复、价格的极端值等),我们需要对数据进行过滤,确保后续分析的准确性。

在本研究中,数据清洗和预处理的具体步骤包括:

**去除重复数据**:检查商品ID是否有重复记录,去除重复的条目。

**处理缺失值**:对于价格、销量等重要字段的缺失数据,我们采用插值或均值填补等方法进行处理。

**标准化字段格式**:确保所有数值字段如价格、销量等保持一致的格式,便于后续的分析。

经过数据清洗后,我们得到了更加干净和结构化的数据,能够为后续的分析和可视化提供基础。
# %% [markdown] cell-3e50bf8d15a1
### 代码片段1


1. `df['商品ID'].duplicated().any()`:检查 `商品ID` 列是否有重复记录,`duplicated()` 返回一个布尔 Series,表示每一行是否为重复项,`any()` 检查是否有 `True`(即存在重复记录)。
2. `df.drop_duplicates(subset=['商品ID'], keep='first')`:去除 `商品ID` 列中的重复项,`keep='first'` 表示保留第一次出现的记录,删除后续重复的记录。

这样,代码会检查是否有重复的 `商品ID`,如果有,就去除重复记录并保留每个 `商品ID` 的第一条记录。

### 代码片段2

这段代码定义了一个函数 `clean_month_sales`,用于处理 `pandas` DataFrame 中的“月销量”字段。然后,使用 `apply` 方法将这个函数应用到 DataFrame 的 `月销量` 列,以对每个元素进行处理。下面是代码的详细解析:

### 1. **函数** `clean_month_sales` 定义:

```
def clean_month_sales(sales_str):
    if pd.isna(sales_str):
        return None
```

* `sales_str` 是函数的输入参数,表示“月销量”字段的单个值。
* `pd.isna(sales_str)` 用于检查该值是否为缺失值(`NaN`)。如果是 `NaN`,函数返回 `None`,表示该值不能被处理。

### 2. **去除字符串前后空白:**

```
sales_str = str(sales_str).strip()
```

* `str(sales_str)`:将 `sales_str` 转换为字符串类型,以防原始值不是字符串类型(如数字、日期等)。
* `strip()`:去除字符串的前后空白字符,以便后续匹配和处理。

### 3. **处理包含“本月行业热销”字符串的情况:**

```
if "本月行业热销" in sales_str:
    return 1000
```

* 如果 `sales_str` 中包含 “本月行业热销”,函数直接返回 1000,表示销量为 1000。

### 4. **处理包含“万+”字符串的情况:**

```
elif "万+" in sales_str:
    match = re.search(r'(\d+)', sales_str)
    if match:
        return int(match.group(1)) * 10000
```

* 如果 `sales_str` 中包含 “万+”,表示销量以“万”为单位。
* 使用 `re.search(r'(\d+)', sales_str)` 通过正则表达式匹配字符串中的数字部分。`(\d+)` 匹配一个或多个数字。
* `match.group(1)` 返回匹配到的数字部分(作为字符串),并将其转换为整数。然后,将这个整数乘以 10000,表示实际销量的值(例如,如果字符串是 “2万+”,则返回 `20000`)。

### 5. **处理包含“+人收货”字符串的情况:**

```
elif "+人收货" in sales_str:
    match = re.search(r'(\d+)', sales_str)
    if match:
        return int(match.group(1))
```

* 如果 `sales_str` 中包含 “+人收货”,表示销量为一些人购买了该商品。
* 同样,使用正则表达式 `re.search(r'(\d+)', sales_str)` 来匹配数字部分,并将其转换为整数。
* 返回匹配到的数字,表示实际销量。

### 6. **尝试将字符串转换为整数:**

```
try:
    return int(sales_str)
except ValueError:
    return None
```

* 如果以上三种情况都没有匹配到,最后尝试将 `sales_str` 直接转换为整数。
* 如果转换成功,则返回该整数值,表示销量的数值。
* 如果 `sales_str` 无法转换为整数(例如包含非数字字符),则捕获 `ValueError` 异常并返回 `None`,表示该值无法处理。

### 7. **应用函数到 DataFrame 的“月销量”列:**

```
df['月销量'] = df['月销量'].apply(clean_month_sales)
```

* `df['月销量']` 是 `pandas` DataFrame 中的“月销量”列。
* 使用 `apply(clean_month_sales)` 将 `clean_month_sales` 函数应用到 `月销量` 列中的每个元素。
  * 这会逐个处理 `月销量` 列的所有值,基于前面定义的规则来清洗和转换这些值。

### 总结:

这段代码的作用是根据不同的规则来处理“月销量”字段的数据,规范化这些数据,使它们统一为整数形式。具体处理方式包括:

* 对于“本月行业热销”直接设定为 1000;
* 对于含有“万+”的,转换为以万为单位的实际数值;
* 对于含有“+人收货”的,提取数字并作为销量;
* 对于其他情况,直接将字符串转换为整数;
* 如果无法转换为整数,则返回 `None`。

最终,这个函数被应用到 `df['月销量']` 列中,清洗并处理了该列的所有数据。

### 代码片段3


1. `df['价格'] <= 1000` 会生成一个布尔值 Series,表示 `价格` 列中每个元素是否小于等于 1000。
2. `df = df[df['月销量'] >= 0]`会筛选出销量大于等于0的所有元素。
3. 使用 `df[...]` 语法,将这个布尔 Series 作为索引过滤出符合条件的记录。

\