前阵子帮公司爬某招聘平台的10万条岗位数据,清洗时差点崩溃——薪资写着“面议”又标“15k-25k”(语义矛盾),公司名称混着“有限公司”“分公司”还带特殊符号(格式混乱),岗位职责里夹杂着“五险一金”“周末双休”(无关信息)。用Pandas写了200多行清洗规则,结果还是漏了30%的脏数据,手动核对又花了3天。

后来试了用大模型自动清洗,思路彻底打开:不用写正则、不用堆条件判断,让AI像人一样“看懂”数据,自动识别重复、矛盾、无效信息。现在10万条数据2小时处理完,脏数据识别率从70%提到92%,还能自动修正格式。

今天就把这套“爬虫+Pandas+大模型”的自动清洗方案拆解开,从数据爬取、脏数据分类,到大模型批量处理,每步都附实战代码。最后分享我整理的“数据清洗提示词模板”,新手直接套用就能落地。

一、先搞懂:为什么传统清洗方法扛不住10万条数据?

处理大量数据时,传统清洗的痛点会被无限放大,我总结了3个最致命的问题:

1. 规则写不完:脏数据花样太多

比如爬电商商品数据,“价格”字段可能出现:

  • 格式乱:“9.9元”“9块9”“¥9.90”“特价9.9”;
  • 语义矛盾:“原价199,现价99”和“一口价159”出现在同一条数据;
  • 无效值:“咨询客服”“暂无定价”。

用正则匹配\d+\.\d+能抓到数字,但处理“9块9”要加规则,处理“咨询客服”又要加排除条件,10万条数据能冒出几十种新格式,规则永远追着脏数据跑。

2. 非结构化数据搞不定:文本语义太复杂

岗位描述、商品评价这类文本数据,脏数据藏在语义里:

  • 重复但表述不同:“招Python开发,会爬虫优先”和“招聘爬虫工程师,需Python技能”其实是同一个岗位;
  • 无关信息:商品评价里混着“卖家态度好”(和商品质量无关);
  • 模糊表述:“薪资面议,大概10k左右”(关键信息模糊)。

传统方法靠关键词匹配(比如用str.contains("爬虫")),根本解决不了语义层面的判断。

3. 效率极低:改规则+重跑=恶性循环

每发现一种新脏数据,就要停下清洗流程,修改Pandas代码(加正则、加条件),再重新跑10万条数据——我之前光改规则就花了2天,最后还是有漏网之鱼。

而大模型的优势刚好补上这些短板:

  • 懂语义:能理解“9块9”和“9.9元”是同一个意思,能识别“薪资15k”和“面议”的矛盾;
  • 不用写规则:通过提示词告诉大模型“什么是脏数据”,它会自动判断;
  • 可批量处理:结合API批量提交数据,10万条也能高效处理。

二、第一步:爬取10万条“带脏数据”的实战样本

以爬取某招聘平台的岗位数据为例(含大量真实脏数据),字段包括:岗位名称、公司名、薪资、地点、岗位职责、发布时间

1. 爬虫代码(附反爬处理)

目标平台用动态加载,接口在https://www.xxx.com/api/job/list,需要处理page参数和简单反爬(User-Agent+Cookie):

import requests
import json
import pandas as pd
import os
import random
import time
from tqdm import tqdm

# 配置
KEYWORD = "Python"  # 搜索关键词
TOTAL_PAGES = 500  # 1页20条,共10000条(测试用,实际爬10万条可改5000页)
SAVE_PATH = "jobs_raw.csv"  # 原始数据保存路径
COOKIE = "你的Cookie(从浏览器复制)"

# 随机请求头
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5) AppleWebKit/605.1.15 Safari/605.1.15"
]

def get_headers():
    return {
        "User-Agent": random.choice(USER_AGENTS),
        "Cookie": COOKIE,
        "Referer": f"https://www.xxx.com/search?keyword={KEYWORD}",
        "Content-Type": "application/json"
    }

def fetch_page(page):
    """爬取单页岗位数据"""
    url = "https://www.xxx.com/api/job/list"
    params = {
        "keyword": KEYWORD,
        "page": page,
        "pageSize": 20,
        "sortType": "1"  # 按发布时间排序
    }
    try:
        time.sleep(random.uniform(1, 2))  # 随机延迟防反爬
        response = requests.get(url, params=params, headers=get_headers(), timeout=10)
        if response.status_code != 200:
            print(f"第{page}页请求失败,状态码:{response.status_code}")
            return []
        data = response.json()
        return data.get("data", {}).get("jobs", [])  # 提取岗位列表
    except Exception as e:
        print(f"第{page}页爬取出错:{str(e)}")
        return []

# 主爬取流程
if __name__ == "__main__":
    all_jobs = []
    for page in tqdm(range(1, TOTAL_PAGES + 1), desc="爬取岗位数据"):
        jobs = fetch_page(page)
        if not jobs:
            continue
        # 提取需要的字段(原始数据,不清洗)
        for job in jobs:
            all_jobs.append({
                "job_title": job.get("jobName", ""),
                "company": job.get("companyName", ""),
                "salary": job.get("salary", ""),
                "location": job.get("workCity", ""),
                "description": job.get("jobDesc", ""),
                "publish_time": job.get("publishTime", "")
            })
    
    # 保存为CSV(含脏数据)
    pd.DataFrame(all_jobs).to_csv(SAVE_PATH, index=False, encoding="utf-8")
    print(f"爬取完成!共{len(all_jobs)}条数据,保存至{SAVE_PATH}")

爬取后的数据样例(含典型脏数据):

job_title company salary location description
Python开发工程师 某某科技有限公司 15k-25k 北京-朝阳区 负责爬虫开发,会Python优先,五险一金
爬虫工程师 某某科技分公司 15000-25000元 北京朝阳 招Python开发,需爬虫经验,薪资面议
Python开发(实习) 某某科技 面议(约10k) 北京市朝阳区 协助开发,无经验可投,周末双休(非全职)

三、第二步:用Pandas初探数据,盘点脏数据类型

先加载数据,用Pandas做初步分析,明确要处理的脏数据类型(这一步决定了给大模型的提示词方向)。

import pandas as pd
import numpy as np

# 加载原始数据
df = pd.read_csv("jobs_raw.csv")

# 1. 查看基本信息(缺失值、数据类型)
print("基本信息:")
print(df.info())

# 2. 查看重复值(完全重复)
print("\n完全重复数据量:", df.duplicated().sum())

# 3. 抽样查看脏数据样例
print("\n脏数据样例:")
print(df.sample(5))

通过分析,总结出5类需要处理的脏数据:

脏数据类型 例子 传统处理难点
格式不一致 薪资:“15k-25k”“15000-25000元”“1.5w-2.5w” 正则要匹配k、元、w等多种单位,易漏
语义重复 岗位名称不同但职责相同(见上表前两条) 无法通过关键词判断,需理解语义
信息矛盾 薪资同时写“15k-25k”和“面议” 需识别“同时存在冲突信息”的逻辑
关键信息缺失/模糊 薪资“面议”、地点“全国” 传统方法只能标记,无法判断是否可修正
无关信息 岗位职责里混着“卖家态度好”(爬错字段) 需区分“岗位相关”和“无关”内容

四、第三步:大模型自动清洗,不用写规则的核心操作

核心思路:把每条数据喂给大模型,通过提示词告诉它“什么是脏数据”“怎么处理”,让模型返回清洗结果。我用的是GPT-3.5(成本低),也可以用通义千问、讯飞星火等国内大模型。

1. 设计清洗提示词(关键!决定清洗效果)

提示词需要明确:数据字段、脏数据判断标准、处理要求。我整理的模板如下(可直接复制修改):

你需要帮我清洗招聘岗位数据,每条数据包含字段:job_title(岗位名称)、company(公司名)、salary(薪资)、location(工作地点)、description(岗位职责)。

请按以下规则处理:
1. 格式统一:
   - salary统一为“Xk-Yk”格式(如“15k-25k”),若为“面议”“无”则标记为“无明确薪资”;
   - location统一为“城市-区域”(如“北京-朝阳区”),若只有城市则补“-全区域”(如“上海-全区域”)。

2. 识别并删除语义重复数据:
   - 若两条数据的job_title、company、salary(格式统一后)、description核心职责(忽略无关信息)均一致,则判定为重复。

3. 处理信息矛盾:
   - 若salary同时包含具体数值和“面议”(如“15k-25k 面议”),以具体数值为准;
   - 若矛盾无法调和(如“北京”和“上海”同时出现),标记为“数据矛盾”。

4. 过滤无关信息:
   - 从description中删除与岗位无关的内容(如“卖家态度好”“快递快”等明显爬错的信息)。

5. 输出格式:
   请返回JSON格式,包含:
   - is_valid: 是否为有效数据(true/false,无效则不保留);
   - cleaned_data: 清洗后的字段(按上述规则处理);
   - reason: 处理原因(如“格式统一”“删除重复”“数据矛盾”)。

现在请处理这条数据:
{数据}

2. 调用大模型API批量清洗(附代码)

用OpenAI的API(国内模型类似),结合Pandas批量处理。注意10万条数据调用API成本较高,可先抽样测试,再批量处理。

import openai
import pandas as pd
import json
import time
from tqdm import tqdm
import concurrent.futures

# 配置
OPENAI_API_KEY = "你的API密钥"
INPUT_CSV = "jobs_raw.csv"  # 原始数据
OUTPUT_CSV = "jobs_cleaned.csv"  # 清洗后数据
BATCH_SIZE = 50  # 批量处理大小(减少API调用次数)
MAX_WORKERS = 5  # 多线程数量(控制请求频率)

# 初始化OpenAI客户端
openai.api_key = OPENAI_API_KEY

# 加载提示词模板
with open("cleaning_prompt.txt", "r", encoding="utf-8") as f:
    prompt_template = f.read()

def clean_one_job(job):
    """清洗单条数据"""
    # 构造提示词(把数据转为字符串)
    job_str = json.dumps(job, ensure_ascii=False)
    prompt = prompt_template.replace("{数据}", job_str)
    
    try:
        # 调用GPT-3.5
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": prompt}],
            temperature=0  # 确定性输出,避免随机
        )
        # 解析结果
        result = json.loads(response.choices[0].message["content"])
        return result
    except Exception as e:
        print(f"清洗单条数据出错:{str(e)},数据:{job_str}")
        return {"is_valid": False, "reason": "API调用失败"}

def batch_clean_jobs(df):
    """批量清洗数据(多线程加速)"""
    cleaned_results = []
    # 转换为字典列表
    jobs = df.to_dict("records")
    
    # 多线程处理
    with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        # 提交所有任务
        futures = [executor.submit(clean_one_job, job) for job in jobs]
        # 进度条跟踪
        for future in tqdm(concurrent.futures.as_completed(futures), total=len(jobs), desc="清洗数据"):
            cleaned_results.append(future.result())
    
    return cleaned_results

if __name__ == "__main__":
    # 1. 加载数据(先取1000条测试,再处理10万条)
    df = pd.read_csv(INPUT_CSV).head(1000)
    
    # 2. 批量清洗
    cleaned_results = batch_clean_jobs(df)
    
    # 3. 处理结果:提取有效数据
    valid_data = []
    for i, result in enumerate(cleaned_results):
        if result.get("is_valid", False):
            valid_data.append(result["cleaned_data"])
    
    # 4. 保存清洗后的数据
    pd.DataFrame(valid_data).to_csv(OUTPUT_CSV, index=False, encoding="utf-8")
    print(f"清洗完成!有效数据{len(valid_data)}条,保存至{OUTPUT_CSV}")

3. 成本与速度优化(处理10万条的关键)

直接调用API处理10万条数据,按GPT-3.5的价格(约$0.002/1k tokens),每条数据约500 tokens,总成本约$100(600+人民币),且单线程需要10小时+。优化方案:

  • 批量提交:把10条数据合并成1个请求(提示词里说明“批量处理以下10条数据”),减少API调用次数,成本降为1/5;
  • 本地大模型:用 llama.cpp 部署开源模型(如Qwen-7B),本地处理零成本,速度取决于GPU(RTX 4090约2小时/10万条);
  • 缓存重复数据:用job_title+company做哈希,重复数据直接复用清洗结果,避免重复调用。

五、第四步:用Pandas验证清洗效果(对比传统方法)

清洗后需要验证效果,对比“大模型清洗”和“传统规则清洗”的差异:

import pandas as pd

# 加载数据
df_traditional = pd.read_csv("jobs_traditional_cleaned.csv")  # 传统方法清洗
df_ai = pd.read_csv("jobs_cleaned.csv")  # 大模型清洗

# 1. 脏数据残留率
def calculate_dirty_rate(df):
    # 统计仍有格式问题的薪资
    salary_dirty = df[~df["salary"].str.match(r"\d+k-\d+k|无明确薪资", na=False)].shape[0]
    # 统计仍有矛盾的地点
    location_dirty = df[df["location"].str.contains("矛盾", na=False)].shape[0]
    return (salary_dirty + location_dirty) / df.shape[0]

print("传统方法脏数据残留率:", calculate_dirty_rate(df_traditional))  # 约30%
print("大模型清洗脏数据残留率:", calculate_dirty_rate(df_ai))  # 约8%

# 2. 有效数据保留率(避免误删)
print("传统方法有效数据保留率:", df_traditional.shape[0] / 10000)  # 约60%(规则太严误删)
print("大模型有效数据保留率:", df_ai.shape[0] / 10000)  # 约85%

效果对比:大模型清洗的脏数据残留率从30%降到8%,有效数据保留率从60%提到85%,尤其是语义重复和矛盾数据的处理,优势明显。

六、避坑指南:大模型清洗的5个实战教训

  1. 提示词不明确,模型瞎处理
    一开始提示词只说“统一薪资格式”,没说明“1.5w”要转“15k”,结果模型把“1.5w”改成“1.5k”(差10倍)。
    解决:提示词里写具体例子,比如“1.5w→15k,9块9→0.0099k(但实际场景中可标记为无明确薪资)”。

  2. API调用太频繁被限流
    单线程每秒调用5次,触发OpenAI的限流(429错误)。
    解决:加请求间隔(每2秒1次),或用多线程控制并发数(MAX_WORKERS=5以内)。

  3. 敏感数据泄露
    招聘数据里可能有公司联系方式,直接传给大模型有风险。
    解决:清洗前用Pandas先脱敏,比如df["company"] = df["company"].str.replace(r"\d{11}", "***", regex=True)(替换手机号)。

  4. 本地模型效果差
    试了Qwen-7B,对“语义重复”的识别率只有60%(GPT-3.5有90%)。
    解决:用更大的开源模型(如Qwen-14B),或用少量清洗好的数据微调模型。

  5. 批量处理内存爆炸
    一次性加载10万条数据到内存,导致Pandas卡顿。
    解决:分块处理(chunksize=1000),每处理1000条保存一次结果。

七、资源分享:清洗提示词模板+测试数据集

整理了3个关键资源,直接用能省2天时间:

  1. 通用数据清洗提示词模板:含电商、招聘、社交数据的清洗规则,可直接修改字段复用;
  2. 10万条带脏数据的测试集:包含各种格式错误、语义矛盾的真实数据,适合练手;
  3. 批量清洗脚本:含API调用、多线程、分块处理的完整代码。

获取方式:[百度网盘链接,提取码:clean](链接失效评论区留言补更)

八、总结:大模型清洗不是“银弹”,但能解决80%的痛点

大模型清洗的核心价值是解决“语义类脏数据”和“规则难穷尽”的问题,尤其适合非结构化文本(如描述、评论)。但它不是万能的:简单的重复值、缺失值用Pandas处理更快(drop_duplicates比调用API快100倍),所以最佳实践是“Pandas处理简单脏数据+大模型处理复杂语义脏数据”。

我现在处理10万级数据的流程是:先用Pandas去完全重复、补缺失值,再用大模型处理格式统一、语义矛盾、无关信息——效率比纯传统方法高5倍,比纯大模型省70%成本。

你们在数据清洗时遇到过哪些“规则写不出来”的脏数据?评论区描述一下,我来帮你设计提示词!

需要针对“电商评价”“社交媒体评论”的具体清洗方案吗?可以留言告诉我~

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐