最近有项目需要去某个文件夹里面,获取所有XML文件,然后从XML文件中查找特定节点中查找是否有特定信息。
为了便于获取所有文件信息,直接用bat文件每天自动运行生成一个文件列表list信息供查看。
cd /d %~dp0 dir /s /b *.* > FileList.txt
所以接下来要做的事情是从该FileList.txt文件中查找到所有XML文件,然后打开每个XML文件查找是否包含指定节点信息。
import os.path from lxml import etree TARGET = r'specific_info' xml_files_list = [] with open(r'C:\test\FileList.txt', 'r') as f: for line in f.readlines(): if line.strip().endswith('_2_.xml'): xml_files_list.append(line) duplicated_id_list = [] result_xml_files = [] for xml_file in xml_files_list: xml_tree_root = etree.parse(xml_file).getroot() detect_install_str = xml_tree_root.xpath('//SPECIFIC_NODE')[0].xpath('string(.)') if TARGET in detect_install_str: # 检查是否此文件名已经检查过了:因为可能在不同文件夹里面有同名的文件 if os.path.basename(xml_file) not in duplicated_id_list: duplicated_id_list.append(os.path.basename(xml_file)) result_xml_files.append(xml_file) print(result_xml_files)
因为FileList.txt中看到的XML文件有近2w个,最后查询速度很慢,需要1000s+。
所以考虑使用多线程的方式来加快查询速度:
import os from lxml import etree from multiprocessing.dummy import Pool TARGET = r'specific_info' xml_files_list = [] file_name_list = [] with open(r'C:\test\FileList.txt', 'r') as f: for line in f.readlines(): # 先去重,这样就不用在读取XML的时候去重了 if line.strip().endswith('_2_.xml') and os.path.basename(line) not in file_name_list: xml_files_list.append(line) # 创建函数用来跑多线程 def handle_xml(xml_file): xml_tree_root = etree.parse(xml_file).getroot() detect_install_str = xml_tree_root.xpath('//SPECIFIC_NODE')[0].xpath('string(.)') if TARGET in detect_install_str: return xml_file p = Pool() results = [] start = time.time() for i in xml_files_list: results.append(p.apply_async(handle_xml, args=(i,))) p.close() p.join() result_xml_files = [x.get() for x in results if x.get()] print(result_xml_files)
用多线程后速度大概是100s+,运行速度有了显著提升。