1、文本数据基础:文本数据的来源与格式(TXT、CSV、JSON、XML),文本编码(ASCII、Unicode、UTF-8),Python中的字符串基础

各位同学好,我是老张。今天咱们聊聊文本数据的基础。说实话,这章看着基础,但我在项目里见过太多人在这上面栽跟头。你想想看,数据清洗的第一步就是读数据,要是连数据格式和编码都搞不定,后面再牛的算法也白搭。

1.1 文本数据的来源与格式

文本数据从哪来?说白了,到处都是。日志文件、用户评论、爬虫抓取的网页、API返回的JSON……我个人的习惯是,拿到数据先看一眼它的“长相”——也就是文件格式。

TXT(纯文本)

最朴素的格式。没有结构,就是一行一行的字符串。适合小规模数据或临时记录。

# 读取TXT文件
with open('data.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()
    for line in lines[:5]:
        print(line.strip())
提示:TXT文件没有元数据,你根本不知道它是什么编码。我建议打开前先用工具检测一下编码,比如 chardet 库。

CSV(逗号分隔值)

表格数据的最爱。每行是一条记录,字段用逗号隔开。注意:字段里如果包含逗号或换行符,需要用引号包裹。

import csv

with open('data.csv', 'r', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
警告:我曾经遇到过一个CSV文件,里面某个字段的文本里含有逗号,结果解析出来字段全错位了。后来我改用 pandas 的 read_csv,设置 quotechar 参数才搞定。

JSON(JavaScript对象表示法)

现在API接口最常用的格式。结构清晰,支持嵌套。非常适合存储复杂的文本数据,比如多层级评论、用户画像等。

import json

with open('data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)
    print(data['comments'][0]['text'])
重点:JSON 的 key 必须是双引号,单引号会报错。我刚开始写爬虫时经常犯这个错。

XML(可扩展标记语言)

老牌格式,现在用得少了,但在一些遗留系统里还是常见。比如 RSS 订阅、某些金融数据接口。

import xml.etree.ElementTree as ET

tree = ET.parse('data.xml')
root = tree.getroot()
for child in root:
    print(child.tag, child.text)

1.2 文本编码:ASCII、Unicode、UTF-8

嗯,这里要注意。编码问题是我见过最坑的,没有之一。你想想看,同样的“你好”,在不同编码下存成不同的字节序列。读错了就是乱码。

ASCII

最古老的编码,只支持128个字符。英文字母、数字、标点符号。中文?不存在的。一个字节存一个字符。

Unicode

为了解决各国文字编码不统一的问题而生。它给每个字符分配了一个唯一的码点(code point)。比如“中”的码点是 U+4E2D。但 Unicode 只是规定了字符和码点的对应关系,没规定怎么存。

UTF-8

这就是 Unicode 的一种存储方式。变长编码,英文用1个字节,中文用3个字节。兼容 ASCII,所以现在互联网上最流行。

编码 特点 适用场景
ASCII 单字节,仅支持英文 纯英文文本
Unicode 码点体系,不指定存储 字符映射标准
UTF-8 变长,兼容ASCII 网页、文件存储
避坑指南:我曾经处理过一个爬虫项目,对方服务器返回的 HTTP 头里写的是 UTF-8,但实际内容是 GBK 编码。结果解析出来全是乱码。后来我加了一步自动检测编码的逻辑,才彻底解决。

1.3 Python中的字符串基础

Python 3 的字符串,默认就是 Unicode。这一点比 Python 2 强太多了。我记得刚转 Python 3 时,再也不用纠结 str 和 unicode 的转换了。

字符串创建与基本操作

s1 = "Hello, NLP"
s2 = '中文也没问题'
s3 = """多行
字符串"""

# 常用方法
print(s1.lower())      # 转小写
print(s1.split(','))   # 按逗号分割
print(s1.strip())      # 去除首尾空白
print(s1.replace('NLP', '自然语言处理'))

字符串与字节串的转换

这是处理不同编码文件时的核心操作。记住:字符串是给人看的,字节串是给机器存的。

# 字符串 -> 字节串(编码)
text = "你好"
bytes_data = text.encode('utf-8')
print(bytes_data)  # b'\xe4\xbd\xa0\xe5\xa5\xbd'

# 字节串 -> 字符串(解码)
decoded_text = bytes_data.decode('utf-8')
print(decoded_text)  # 你好
重点:编码和解码必须用同一套规则。你用 UTF-8 编码,却用 GBK 解码,出来的就是乱码。我建议所有项目统一用 UTF-8,省心。

正则表达式入门

文本清洗离不开正则。虽然看着像天书,但掌握几个常用模式就够了。

import re

text = "我的电话是138-1234-5678,邮箱是zhang@example.com"

# 提取电话号码
phone = re.search(r'\d{3}-\d{4}-\d{4}', text)
print(phone.group())  # 138-1234-5678

# 提取邮箱
email = re.search(r'\w+@\w+\.\w+', text)
print(email.group())  # zhang@example.com
个人经验:正则表达式里用 r 前缀(原始字符串)可以避免反斜杠转义的麻烦。我刚开始写正则时经常被这个坑到。

好了,文本数据的基础就这些。说白了,格式决定你怎么读,编码决定你能不能读对,字符串操作决定你怎么处理。下一章咱们聊聊具体的数据清洗技巧,比如去重、去停用词、分词这些实战内容。