优化Python脚本以解析xml
我正在使用Python和Beautifulsoup解析美国专利XML文件(从下载);解析后的数据导出到MYSQL数据库 每年的数据包含近20-30万项专利——这意味着解析20-30万个xml文件 我运行python脚本的服务器功能非常强大——16个内核,160 Gig的RAM,等等。但解析一年的数据仍然需要将近3天的时间。 我已经学习和使用python两年了,所以我可以完成一些事情,但不知道如何以最有效的方式完成。我正在读 如何优化下面的脚本以使其高效 任何指导都将不胜感激 代码如下:优化Python脚本以解析xml,python,mysql,xml,optimization,beautifulsoup,Python,Mysql,Xml,Optimization,Beautifulsoup,我正在使用Python和Beautifulsoup解析美国专利XML文件(从下载);解析后的数据导出到MYSQL数据库 每年的数据包含近20-30万项专利——这意味着解析20-30万个xml文件 我运行python脚本的服务器功能非常强大——16个内核,160 Gig的RAM,等等。但解析一年的数据仍然需要将近3天的时间。 我已经学习和使用python两年了,所以我可以完成一些事情,但不知道如何以最有效的方式完成。我正在读 如何优化下面的脚本以使其高效 任何指导都将不胜感激 代码如下: fro
from bs4 import BeautifulSoup
import pandas as pd
from pandas.core.frame import DataFrame
import MySQLdb as db
import os
cnxn = db.connect('xx.xx.xx.xx','xxxxx','xxxxx','xxxx',charset='utf8',use_unicode=True)
def separated_xml(infile):
file = open(infile, "r")
buffer = [file.readline()]
for line in file:
if line.startswith("<?xml "):
yield "".join(buffer)
buffer = []
buffer.append(line)
yield "".join(buffer)
file.close()
def get_data(soup):
df = pd.DataFrame(columns = ['doc_id','patcit_num','patcit_document_id_country', 'patcit_document_id_doc_number','patcit_document_id_kind','patcit_document_id_name','patcit_document_id_date','category'])
if soup.findAll('us-citation'):
cit = soup.findAll('us-citation')
else:
cit = soup.findAll('citation')
doc_id = soup.findAll('publication-reference')[0].find('doc-number').text
for x in cit:
try:
patcit_num = x.find('patcit')['num']
except:
patcit_num = None
try:
patcit_document_id_country = x.find('country').text
except:
patcit_document_id_country = None
try:
patcit_document_id_doc_number = x.find('doc-number').text
except:
patcit_document_id_doc_number = None
try:
patcit_document_id_kind = x.find('kind').text
except:
patcit_document_id_kind = None
try:
patcit_document_id_name = x.find('name').text
except:
patcit_document_id_name = None
try:
patcit_document_id_date = x.find('date').text
except:
patcit_document_id_date = None
try:
category = x.find('category').text
except:
category = None
print doc_id
val = {'doc_id':doc_id,'patcit_num':patcit_num, 'patcit_document_id_country':patcit_document_id_country,'patcit_document_id_doc_number':patcit_document_id_doc_number, 'patcit_document_id_kind':patcit_document_id_kind,'patcit_document_id_name':patcit_document_id_name,'patcit_document_id_date':patcit_document_id_date,'category':category}
df = df.append(val, ignore_index=True)
df.to_sql(name = 'table_name', con = cnxn, flavor='mysql', if_exists='append')
print '1 doc exported'
i=0
l = os.listdir('/path/')
for item in l:
f = '/path/'+item
print 'Currently parsing - ',item
for xml_string in separated_xml(f):
soup = BeautifulSoup(xml_string,'xml')
if soup.find('us-patent-grant'):
print item, i, xml_string[177:204]
get_data(soup)
else:
print item, i, xml_string[177:204],'***********************************soup not found********************************************'
i+=1
print 'DONE!!!'
从bs4导入美化组
作为pd进口熊猫
从pandas.core.frame导入数据帧
将MySQLdb作为数据库导入
导入操作系统
cnxn=db.connect('xx.xx.xx.xx','xxxxx','xxxxx','xxxxx',charset='utf8',使用unicode=True)
def分离的xml(填充):
文件=打开(填充“r”)
缓冲区=[file.readline()]
对于文件中的行:
如果line.startswith(“这里是一个,因为当前该代码将在1个线程、1个核心上运行
删除所有try/except语句并正确处理代码。异常代价高昂
运行a以查找阻塞点,并对这些阻塞点进行多线程处理或找到一种方法以减少处理次数。使用profiler在一个小数据集上运行它,查看问题所在。此外,删除所有try/except子句并正确检查。捕获错误的成本很高。这件事多久打印一次到控制台?每个文件一次?缓冲打印i它也很昂贵,如果可能的话,可以少打印。你也可以将程序并行化以在更多线程上运行。这将只在一个内核、一个线程上运行。是的,我正在研究如何使用所有CPU。我正在使用nohup运行脚本,以便将输出写入“nohup.out”"此外,我需要检查这个特定的值是否存在,因为有数百万条记录,如果这个值不存在,脚本可能会崩溃;除非有更好的检查方法,否则可能会切换到lxml.html
?一些人体验到BeautifulSoup
比lxml.html
,f.e:16个线程慢得多(或16个单独的作业,每个作业处理1/16的文件)的运行速度将是原来的16倍——可能每年5个小时。我已经阅读了多线程教程,但我仍然不知道如何将其应用到我的场景中。@rickjames-我可以获得文件夹中的文件列表,并将它们划分为16个要分析的线程;我如何告诉程序并行运行这些线程?它们是线程,如果有足够的资源,它们总是并行运行可用。只要它们不被阻止等待相同的资源。另一件事。我不知道你的文件有多大,但你可能想读入,比如说,160个文件并在其上运行,然后读入另外160个文件。磁盘访问总共花费时间53个文件-每个文件包含近4000个单独xml文件的串联文本-基本上,程序读取每个大文件,将其拆分为单个xml文件并解析xml。如果我将整个任务拆分为10个线程,则每个线程都会生成5个文件。只有53个(而不是16个)。简单地生成53个线程(或进程)可能更简单让他们争夺资源。这种方法的关键资源是RAM。“交换”会减慢速度,使这种方法变得不好。(CPU和/或I/O饱和不会成为问题。)