优化Python脚本以解析xml

优化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

我正在使用Python和Beautifulsoup解析美国专利XML文件(从下载);解析后的数据导出到MYSQL数据库

每年的数据包含近20-30万项专利——这意味着解析20-30万个xml文件

我运行python脚本的服务器功能非常强大——16个内核,160 Gig的RAM,等等。但解析一年的数据仍然需要将近3天的时间。

我已经学习和使用python两年了,所以我可以完成一些事情,但不知道如何以最有效的方式完成。我正在读

如何优化下面的脚本以使其高效

任何指导都将不胜感激

代码如下:

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饱和不会成为问题。)