2、数据采集与标注:公开数据集获取、爬虫基础(Requests/Scrapy)、数据清洗与标注工具(LabelImg)入门

大家好,欢迎来到第二章。

上一章我们聊了项目怎么规划,环境怎么搭。这一章,咱们得解决一个很现实的问题——数据从哪来?

说实话,我见过不少同学,模型架构背得滚瓜烂熟,一到自己动手就卡住了。为啥?手里没数据。你想想看,巧妇难为无米之炊嘛。这一章,我就带你把这「米」的问题搞定。

2.1 公开数据集:站在巨人的肩膀上

做项目最省力的办法,就是直接用别人整理好的数据集。我个人习惯,先上这几个地方翻一翻:

  • Kaggle Datasets:社区活跃,质量参差不齐,但胜在种类多。我经常在上面找一些竞赛用的基准数据集。
  • Papers with Code:这个好,论文和数据集绑在一起。你想复现哪篇论文,直接去这里找对应的数据。
  • 天池、DataFountain:国内平台,中文场景的数据集比较多,比如电商评论、中文OCR之类的。
  • UCI Machine Learning Repository:老牌数据集库,适合做基础研究,数据都比较干净。

不过要注意,公开数据集不是拿来就能用的。我在项目中遇到过一个问题:一个公开的人脸数据集,标注框的格式跟我的模型要求不一样。嗯,这里要注意,数据集的「领域匹配度」和「标注格式」,这两个点一定要先确认好。

小技巧: 下载数据集前,先看一眼它的 README 文件。里面通常会写清楚数据是怎么采集的、标注格式是什么、有没有版权限制。花5分钟看这个,能省你后面2小时的调试时间。

2.2 爬虫基础:自己动手,丰衣足食

公开数据集找不到你要的?那就自己爬。说白了,爬虫就是模拟浏览器去访问网页,然后把网页上的数据拿下来。

我刚开始学爬虫时,总觉得这东西很神秘。其实核心就两件事:发请求解析响应

2.2.1 Requests 库:最基础的爬虫工具

Python 的 requests 库,是爬虫的入门标配。它帮你把 HTTP 请求封装得特别简单。

import requests

# 发一个 GET 请求
url = "https://example.com/api/data"
response = requests.get(url)

# 检查状态码
if response.status_code == 200:
    # 解析 JSON 数据
    data = response.json()
    print(data)
else:
    print(f"请求失败,状态码:{response.status_code}")

你看,就这么几行代码,就能拿到数据了。不过,真实场景没这么简单。我曾经爬一个电商网站,直接发请求返回的是 403 错误。为啥?因为网站检测到我不是真人浏览器。

解决办法也很简单——加个请求头,伪装成浏览器:

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
避坑指南: 我曾经因为爬取频率太高,IP 被网站封了24小时。后来我养成了习惯,每次请求之间加个 time.sleep(1),模拟人的浏览速度。尊重别人的服务器,也是保护自己的数据源。

2.2.2 Scrapy 框架:批量爬取的正确姿势

如果你要爬的数据量很大,比如几千页的商品信息,用 Requests 一个个写循环就太累了。这时候就该 Scrapy 上场了。

Scrapy 是一个异步爬虫框架。说白了,它就像一个流水线工厂:你告诉它「去哪个网站、拿什么数据」,它自动帮你并发处理,效率高得多。

一个简单的 Scrapy 爬虫大概长这样:

import scrapy

class MySpider(scrapy.Spider):
    name = "example_spider"
    start_urls = ["https://example.com/page/1"]

    def parse(self, response):
        # 提取当前页的数据
        for item in response.css("div.product"):
            yield {
                "title": item.css("h2::text").get(),
                "price": item.css("span.price::text").get(),
            }

        # 翻到下一页
        next_page = response.css("a.next::attr(href)").get()
        if next_page:
            yield response.follow(next_page, self.parse)

你想想看,用 Requests 你要手动写循环、处理异常、控制并发。Scrapy 把这些都封装好了,你只需要关注「怎么提取数据」就行。

我的建议: 小规模数据(几百条以内)用 Requests 就够了,灵活、好调试。大规模数据(上万条)用 Scrapy,省时省力。别一上来就上框架,也别一直手写循环,看场景选工具。

2.3 数据清洗:把「脏数据」变成「干净数据」

数据拿到手了,但别高兴太早。真实世界的数据,脏得超乎你想象。我见过一个数据集,里面居然有 HTML 标签、乱码、空值混在一起。这种数据直接喂给模型,模型能学出个啥?

数据清洗,说白了就是做三件事:

  1. 去重:重复的数据会让模型产生偏见。
  2. 处理缺失值:要么删掉,要么填充(比如用均值、中位数)。
  3. 格式统一:比如日期格式、文本编码,全部转成统一的格式。

举个例子,用 Pandas 清洗 CSV 文件:

import pandas as pd

# 读取数据
df = pd.read_csv("raw_data.csv")

# 去重
df = df.drop_duplicates()

# 处理缺失值:删除包含空值的行
df = df.dropna()

# 格式统一:把文本转小写
df["text"] = df["text"].str.lower()

# 保存清洗后的数据
df.to_csv("clean_data.csv", index=False)

嗯,这里要注意,清洗规则不是固定的。你得先看看数据长什么样,再决定怎么洗。我一般会先打印 df.info()df.describe(),快速了解数据概况。

2.4 标注工具入门:LabelImg 实战

如果你做的是目标检测项目,那就绕不开数据标注。说白了,就是告诉模型:「这张图里,这个框框里是一只猫。」

LabelImg 是我用得最多的标注工具。它免费、开源、跨平台,支持 YOLO 和 Pascal VOC 两种主流格式。

2.4.1 安装与启动

安装很简单,一行命令:

pip install labelImg

然后在终端输入 labelImg 就能启动了。界面很简洁,左边是工具栏,中间是图片区域。

2.4.2 标注流程

  1. 打开图片文件夹。
  2. 点击「Create RectBox」,在目标周围画框。
  3. 输入标签名称(比如 "cat"、"dog")。
  4. 保存标注结果(默认生成 XML 文件)。
  5. 按快捷键 W 继续下一张。

我个人习惯,标注前先定好标签规范。比如所有类别都用英文小写,不要混用大小写。我曾经因为 "Cat" 和 "cat" 两个标签,导致模型训练时报错,排查了半天才发现是大小写问题。

效率技巧: LabelImg 支持快捷键。记住这几个:W 画框,A 上一张,D 下一张,Ctrl+S 保存。熟练之后,标注速度能快一倍。

2.5 本章小结

这一章我们走完了数据采集到标注的全流程。你想想看,从找公开数据集,到用爬虫自己抓,再到清洗脏数据,最后用 LabelImg 打标签——每一步都是在为模型准备「食物」。数据质量决定了模型的天花板,这话一点不夸张。

下一章,我们会正式进入模型训练环节。到时候你会发现,数据准备得越充分,训练过程就越顺畅。咱们下章见。