记一次800多万XML文本文件预处理经历

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

一.背景

由于某些需求,现需对系统在最近几个月生成的xml文件进行预处理,提取标签内的数据进行分析。这些需要预处理的数据大概有280GB左右880多万,存放在gysl目录下,gysl的下一层按天命名,分为若干个目录,接下来一层目录下又有多个目录,我们所需的xml目录就在这一层。我们现在需要将此目录下面的xml文件使用Python脚本进行处理,并将处理结果按天(与源文件一致)保存到~/temp目录下。

二.操作过程

2.1 Python脚本准备。

#!/usr/bin/python3
# -*- coding:utf-8 -*-
import glob,os,sys, re
from concurrent.futures import ProcessPoolExecutor
import argparse
import random

def find_xs(str, list):
	i = 0
	for i in range(0,len(str)):
		if str[i] in list:
			return i
	return -1

def segement_aux(para, OUT, sep_list, max_length, merge_prob):
	pos = 0
	res_sentence = ""
	sentence_size = 0
	while True:
		#segment one line.
		pos = find_xs(para,sep_list)
		if pos == -1:
			break
		cur_sentence = para[:pos+1].strip()
		cur_sentence_filtering = cur_sentence
		res_sentence = res_sentence + cur_sentence_filtering
		sentence_size = sentence_size + 1
		if sentence_size == 2:
			OUT.write(res_sentence + '\n')
		else:
			rand = random.random() 
			if rand > merge_prob:
				OUT.write(res_sentence + '\n')
				res_sentence = ""
				sentence_size = 0
			else:
				sentence_size = sentence_size + 1
		para = para[pos+1:]
	
def loadXMLfile(inputfile):
	sep_list= ['。', '?', '!']
	targetfolder = "Target"
	max_length = 100000
	merge_prob = 0.6
	basefilename =os.path.basename(inputfile)
	outputfile = targetfolder + '/'+ os.path.splitext(basefilename)[0] + ".tsv"
	textSessionPattern = re.compile(r'<text>(.*?)</text>\s*',  re.I|re.MULTILINE)
	OUT = open(outputfile, 'w',encoding="utf8")
	for line in open(inputfile,encoding="utf8"):
		line = line.strip().rstrip("\r\n")
		alltextsessions = re.findall(textSessionPattern, line)
		for textsession in alltextsessions:
			textsession = re.sub(r'\t', r' ', textsession)
			textsession = re.sub(r'\<[^\<|\>]+\>', r'', textsession)
			textsession = re.sub(r'\{[^\}|\{]+\}', r'', textsession)
			textsession = re.sub(r'\s+',r'',textsession)
			OUT.write(textsession+'\n')
	OUT.close()
	return outputfile
	
def processXMLfilesWithThreads(input):
	with ProcessPoolExecutor() as executor:
		xmlfiles = glob.glob(input + "/*.xml")
		for xmlfile, outputfile in zip( xmlfiles, executor.map( loadXMLfile, xmlfiles) ):
			print("Processed" + outputfile)

if __name__ == '__main__':
	ap = argparse.ArgumentParser()
	ap.add_argument("-i", "--input", required=True, help="the directory of input files")
	args = ap.parse_args()
	processXMLfilesWithThreads(input = args.input)

2.2 Shell脚本准备。

for folder in `find /home/ivandu/gysl -path "*/xml" -print`;do mkdir Target;python3 XMLPreProcess.py --input $folder;mv Target ~/temp/$(echo $folder|awk -F "/" '{print $5}');done

看着有点费劲,改一下:

#!/bin/bash
for folder in `find /home/ivandu/gysl -path "*/xml" -print`;
    do 
        mkdir Target;
        python3 XMLPreProcess.py --input $folder;
        mv Target ~/temp/$(echo $folder|awk -F "/" '{print $5}');
    done

2.3 执行脚本。

此步骤就不展示了,涉及到某些商业机密。在Python脚本所在的目录下,执行Shell脚本就行。

三.遇到问题

3.1 “Argument list too long”。

在执行某目录下的文件移动、复制、删除操作时,发现提示“Argument list too long”,命令执行不成功。这个目录下的文件数量超过30万,操作命令如下:

cp * ~/gysl_test

提示:

-sh: /bin/cp: Argument list too long 

解决方案:

for file in `ls`;do cp $file ~/gysl_test/;done

rm,mv,cat也类似,太忙了也就没继续探讨其他解决方案。

3.2 双for循环执行效率太低。

for folder in `find /home/ivandu/gysl/ -mindepth 2 -maxdepth 2 -print|grep "xml"`;do cd $folder;for file in $(ls);do cp $file ~/gysl_test/;done;done

如果使用这命令来拷贝这些文件的话,那么这一天可能就过去了!这个肯定不妥,必须改进。find也用得不够简洁,后来都进行优化了。

3.3 Python单线程执行效率太低。

Python脚本使用了多线程来进行处理。不过多解释,大家见谅^_^

四.总结

4.1 总体来说今天处理这些数据还是挺给力的,差不多5000秒就完成了。我写了一条命令动态观察了一下。

4.2 正则表达式随时都能用上,要不是处理一下特殊任务和Python多线程,直接一个grep命令写到shell命令或许早就完事了。

4.3 多线程。bash shell中的多线程还不会使用,以后还得加强学习一下。

4.4 就写这么多了,不足之处还望诸位不吝赐教。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

使用Hystrix提高系统可用性

今天稍微复杂点的互联网应用,服务端基本都是分布式的,大量的服务支撑起整个系统,服务之间也难免有大量的依赖关系,依赖都是通过网络连接起来。 ? (图片来源:htt...

22250
来自专栏Jerry的SAP技术分享

如何用代码填充S/4HANA销售订单行项目的数量字段

我的任务是用代码生成S/4HANA销售订单(Sales Order)的行项目,并且填充对应的quantity(数量)值。

9120
来自专栏Ceph对象存储方案

远程管理openresty的reload

默认情况下,nginx/openresty会启动一个root权限运行的master进程,之后再用指定的普通用户权限启动对应的worker,如果需要对整个open...

41150
来自专栏Debian社区

Debian 宣布 Debsources,可搜索软件包源代码

Debian 项目宣布 Debsources,允许浏览和搜索所有 Debian 发行版软件包源代码的 Web 服务,现在是托管在官方Debian基础设施在htt...

14730
来自专栏bboysoul

wordpress信息收集扫描工具WPSeku

wordpress现在是越来越流行了,所以对它的渗透也越来越重要了今天介绍的是一个扫描工具wpseku,可以收集wordpress网站的一些基本信息

11320
来自专栏颇忒脱的技术博客

K8S Ingress环境下,Http Redirect端口丢失问题

近日发现一个问题:应用程序在返回Http Redirect的时候丢失了原先访问的端口。比如,我们这样访问http://IP-A:Port-A/app/delet...

32440
来自专栏向治洪

android studio比较长用的几款插件

不懂安装studio插件,看参考博文:android stuido插件安装:http://blog.csdn.net/liang5630/article/de...

20280
来自专栏小狼的世界

REST风格的应用程序实现

莫笑我老土,因为我确实是最近才听说REST风格的,以前就是觉得 /category/product/pid

8610
来自专栏FreeBuf

GNU/Linux内核新特性引发提权漏洞

image.png SUSE安全研究成员Sebastian Krahmer公布了GNU/Linux内核提权漏洞,最近的GNU/Linux kernel(3.8...

23750
来自专栏张戈的专栏

php5编译安装常见错误和解决办法集锦

最近在给开发同事折腾开发测试环境,其中就有 php 的编译安装。由于每个人的需求不一致,所以也接触到了各种模块编译和集成,中间不乏各种编译依赖报错。 正好,搜了...

50270

扫码关注云+社区

领取腾讯云代金券