尘土与星辰 -1992|第138章|脏数据与容错率|中文
清晨六点。天还没亮透。 林尘睁开眼。堂屋的窗纸泛着灰白。他先没动,而是把左脚从被子里挪出来。纱布已经干硬,边缘渗出一点黄褐色的结痂。他试着用脚趾抓了一下床单。没有知觉。只有脚踝处传来一阵沉闷的胀痛,像塞了一团浸透水的棉花。 他坐起身。穿衣。套上那双鞋底已经磨偏
第138章 脏数据与容错率
清晨六点。天还没亮透。
林尘睁开眼。堂屋的窗纸泛着灰白。他先没动,而是把左脚从被子里挪出来。纱布已经干硬,边缘渗出一点黄褐色的结痂。他试着用脚趾抓了一下床单。没有知觉。只有脚踝处传来一阵沉闷的胀痛,像塞了一团浸透水的棉花。
他坐起身。穿衣。套上那双鞋底已经磨偏的解放鞋。左脚踩下去的瞬间,重心本能地向右倾斜。他停顿两秒,等那股刺痛过去,才扶着门框站起来。
水缸里的水很凉。他舀了一瓢,洗脸。冷水激得太阳穴一紧,困意散了大半。
灶台上放着半个冷馒头。他掰开,就着凉白开咽下去。胃里有了东西,人才能干活。
七点二十。他背上帆布包,出门。
去镇上的路是碎石铺的。昨夜的露水还没干,鞋底踩上去发出细碎的咯吱声。他走得很慢。左脚不能正常发力,只能靠右腿蹬地,左腿像钟摆一样被拖着向前。每走一百米,小腿肌肉就抽紧一次。他停下,靠在路边的槐树上喘气。看着远处的电线杆。一根,两根。数到第五根,再继续走。
八点整。他推开介绍所的铁门。
屋里已经坐了三个人。空气里弥漫着劣质打印纸和碳粉的味道。老赵坐在柜台后面,手里夹着半截烟,正翻着一沓厚厚的表格。
“来了。”老赵抬头看了他一眼,目光在他左脚上停了一秒,没说话,只把一摞用牛皮纸袋装着的文件推过来。“今天的量。三千条。客户信息、发票号、金额、备注。下午五点前交。按件算,一条两分。做完结账。”
林尘点头。拉开椅子坐下。
他拆开纸袋。抽出一张样表。和昨天练习的格式一样,但实际数据要乱得多。有的金额栏里写着“叁仟贰佰”,有的备注栏里夹杂着“加急”“已退”“客户失联”的手写批注。还有几行,字段直接错位,发票号跑到了日期栏里。纸页边缘带着复印机的温热,油墨味刺鼻。
他拿起笔。开始录入。
键盘是那种老式的薄膜键盘,按键发涩,回弹无力。他敲得很慢。眼睛盯着屏幕,手指机械地移动。Ctrl+C,Ctrl+V。切换窗口。核对。回车。
九点。处理了八十条。
十一点。处理了两百条。
手腕开始发酸。肩膀僵硬。左脚的胀痛顺着小腿往上爬。他停下,揉了揉太阳穴。脑子里却在跑另一套逻辑。
手动录入的瓶颈不在手速,在判断。每一条数据都要人眼去识别格式、纠正错位、剔除无效字符。这是重复劳动。重复劳动就有规律。有规律就能抽象成规则。
他翻开随身带的硬壳笔记本。在空白页写下:
规则1:金额字段。可能含中文大写、千分位逗号、纯数字。需统一转为浮点数。
规则2:发票号。12位数字。若含字母或短横线,视为无效,标记跳过。
规则3:备注。非结构化文本。保留原样,但需过滤特殊符号(如*、#、换行符)。
规则4:错位行。若日期栏出现数字串,且长度>6,判定为发票号错位。需整体右移一列。
他写完。合上本子。继续敲键盘。
下午四点五十。最后一行回车。
他站起身。把整理好的Excel文件拖进共享文件夹。老赵走过来,打开核对。鼠标滚轮滑动。抽查了二十条。没报错。
“行。”老赵从抽屉里数出四十块钱,拍在桌上。“明天还有。量可能更大。你能不能接?”
“能。”林尘接过钱。纸币边缘有些毛糙。他仔细对折,放进贴身口袋。
走出介绍所。天阴着。风比早上大。
他先去镇上的卫生所。买了两卷新纱布,一瓶碘伏。花了三块二。剩下的三十六块八。他走到路边的包子铺,买了两个肉包。站在檐下吃完。热气熏得眼睛发酸。
回村的路比早上更难走。左脚已经完全麻木,只能靠右腿硬撑。膝盖承受了双倍的压力。走到村口时,小腿肌肉开始不受控制地痉挛。他扶着土墙,蹲下来。深呼吸。等那股抽痛过去。
晚上七点四十。他推开图书馆侧门的铁栅栏。
旧电脑区在地下室。灯光昏暗。只有六台机器亮着。风扇嗡嗡作响。他挑了最角落的一台。开机。等待。
屏幕亮起。Windows XP的桌面。他打开Python 2.7的IDLE。新建文件。
开始写V2.0。
他先导入模块。import re。import codecs。
定义清洗函数。def clean_row(line):
用正则匹配数字。re.findall(r'[\d,\.]+', amount_str)。替换逗号。转浮点。
加入异常捕获。try...except ValueError:。如果转换失败,记录日志,返回None。
处理错位逻辑。if len(date_col) > 6 and date_col.isdigit(): 交换列。
他写得很慢。每一行都要在脑子里过一遍边界条件。空行怎么处理?全角字符怎么处理?文件读到一半中断怎么办?
九点。代码写完。保存为clean_v2.py。
他把昨天跑通的测试数据替换成今天实际录入的原始文本。点击运行。
命令行窗口弹出。进度条开始滚动。
Processing line 1... OK
Processing line 100... OK
Processing line 500... OK
速度很快。比手动快一百倍。
但跑到第1247行时,屏幕突然停住。
Traceback (most recent call last):
File "clean_v2.py", line 42, in clean_row
UnicodeDecodeError: 'gbk' codec can't decode byte 0xa8 in position 12: illegal multibyte sequence
报错。
林尘盯着屏幕。没有烦躁。只有冷静。
他打开原始文本。跳到第1247行。备注栏里有一个生僻字。客户名字里带了一个“㙓”。GBK编码库里没有这个字。解码失败。程序崩溃。
他靠在椅背上。手指轻轻敲着桌面。
代码能跑通逻辑,但跑不通现实。现实的数据是脏的。是带着历史遗留的编码混乱、人工录入的笔误、系统导出的乱码。你写的规则再严密,也挡不住一个生僻字。商业项目不关心你的算法多优雅,只关心能不能按时交付。漏一行,扣一笔钱。错一个数,客户投诉。
他坐直。修改代码。
把codecs.open的解码方式换成errors='ignore'。或者用utf-8强制覆盖。但这样会丢失信息。
他想了想。在异常捕获里加了一行:except UnicodeDecodeError: return line.encode('utf-8', 'replace').decode('utf-8')。用替换符兜底。不崩溃。只标记。
重新运行。
进度条继续滚动。1247行跳过。1500行。2000行。3000行。
Processed 3000 lines. Success: 2985. Skipped: 15. Errors: 0.
输出文件生成。他打开。数据整齐。金额统一为两位小数。错位行已修正。生僻字变成了问号。
他关掉文件。清理缓存。关机。
走出图书馆。夜风很冷。他慢慢走回村。脚步依旧沉重。但脑子里很清晰。
脚本跑通了。但只是第一步。
老赵明天会给更大的量。五千条。一万条。如果数据源不统一,脚本每次都要改正则。如果甲方要求实时导出,Python的本地运行速度不够。如果老板发现他能自动化,会不会压价?或者,直接让他一个人干三个人的活?
技术是杠杆。但杠杆的支点,不在代码里。在需求里。在谈判里。在你能不能把“清洗数据”变成“交付标准”。
他推开院门。堂屋的灯还亮着。
小满已经睡了。画册摊在桌上。画着一台电脑。屏幕里画着很多齿轮。咬合在一起。
王桂英在里屋咳嗽了两声。没出来。
林尘坐下。翻开账本。
日期:8月7日。
支出:纱布碘伏3.2元。肉包1.5元。
收入:录入结算40元。
余额:35.3元。
脚伤:知觉未恢复。步态依赖右腿。
进度:脚本V2.0跑通。异常捕获已加。生僻字兜底处理。
他停下笔。看着余额。三十五块三。够买一本《正则表达式必知必会》。够交下周的公交费。但不够买一本《设计模式》。不够应对甲方突然改需求。
他合上账本。吹灭台灯。
黑暗落下。左脚的痛感在深夜里变得清晰。像一根细针。一下一下扎在神经上。他闭上眼。脑子里还在跑代码。try...except。正则表达式。容错率。
明天。早八点。报到。晚上。图书馆。脚本V3.0。封装成类。加入日志模块。尝试对接Excel的xlrd库。
路还长。但齿轮已经咬合。余量在减少。时间不等人。
窗外的风停了。远处的狗吠了两声。
他闭上眼。心跳平稳。
明天。八点。键盘。代码。容错率。
路还长。但每一步,都踩在实地上。
枕头边的旧手机震动了一下。屏幕亮起微光。
一条短信。来自老赵。
“明天量加到八千。下午三点前交。能接回个话。”
林尘睁开眼。看着那行字。没有立刻回复。
八千条。手动录入,需要两个人干一天。用脚本,两小时。但数据源如果还是这种混乱的TXT,V2.0的容错率不够。会漏单。漏单就是扣钱。扣钱就是白干。
他坐起身。摸黑打开台灯。光晕昏黄。
他拿起笔。在账本背面写下:
需求变更:量级x2.6。时限缩短1/3。
风险:漏单率。编码混乱。
对策:V3.0需加校验层。跑完后二次比对。
谈判:按量阶梯计价。或要求提供CSV标准源文件。
他写完。放下笔。
手机屏幕暗下去。
他拿起手机。按下回复键。
“能接。但需要源文件格式统一。否则按实际清洗条数结算。”
发送。
屏幕显示“已送达”。
他放下手机。重新躺下。
心跳依旧平稳。但脑子里的齿轮,已经转到了下一个档位。
明天。不止是写代码。是谈规则。
窗外的风又起了。吹动窗纸。沙沙作响。
他闭上眼。等待天亮。
Comments
0 public responses
All visitors can read comments. Sign in to join the discussion.
Log in to comment